better separation, minor fixes
This commit is contained in:
parent
e5867b00a5
commit
cfa1688085
|
@ -0,0 +1,63 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var PromiseA = require('bluebird')
|
||||||
|
, fs = PromiseA.promisifyAll(require('fs'))
|
||||||
|
, path = require('path')
|
||||||
|
, cli = require('cli')
|
||||||
|
;
|
||||||
|
|
||||||
|
cli.parse({
|
||||||
|
blog: ['b', 'Where your blog is, i.e. ~/path/to/blog', 'string', './']
|
||||||
|
//, output: ['o', 'name of output directory within ~/path/to/blog', 'string', './compiled']
|
||||||
|
});
|
||||||
|
|
||||||
|
function serve(blogdir) {
|
||||||
|
var http = require('http')
|
||||||
|
//, https = require('https')
|
||||||
|
, app = require('../server').create({ blogdir: blogdir })
|
||||||
|
, server
|
||||||
|
;
|
||||||
|
|
||||||
|
server = http.createServer(app).listen(65080, function () {
|
||||||
|
console.log("Listening from " + blogdir);
|
||||||
|
console.log("Listening on http://local.dear.desi:" + server.address().port);
|
||||||
|
});
|
||||||
|
//secureServer = https.createServer(app).listen(65043);
|
||||||
|
}
|
||||||
|
|
||||||
|
cli.main(function (args, options) {
|
||||||
|
var command = args[0]
|
||||||
|
, blogdir = options.blog
|
||||||
|
;
|
||||||
|
|
||||||
|
if (!blogdir) {
|
||||||
|
blogdir = path.resolve('./');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fs.existsSync(path.join(options.blog, 'site.yml'))) {
|
||||||
|
console.error("Usage: deardesi [serve|init|post] -b ~/path/to/blog");
|
||||||
|
console.error("(if ~/path/to/blog doesn't yet exist or doesn't have config.yml, site.yml, etc, "
|
||||||
|
+ "try `deardesi init -b ~/path/to/blog'");
|
||||||
|
process.exit(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('init' === command) {
|
||||||
|
console.error("`init' not yet implemented");
|
||||||
|
process.exit(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if ('post' === command) {
|
||||||
|
console.error("`post' not yet implemented");
|
||||||
|
process.exit(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if ('serve' === command) {
|
||||||
|
serve(blogdir);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.error("Usage: deardesi [serve|init|post] -b ~/path/to/blog");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,13 +1,22 @@
|
||||||
angular.module('myApp.services', []).
|
angular.module('myApp.services', []).
|
||||||
factory('Desirae', ['$q', function($q) {
|
factory('Desirae', ['$q', '$http', function ($q, $http) {
|
||||||
var Desi = window.Desi || require('./deardesi').Desi
|
var Desi = window.Desi || require('./deardesi').Desi
|
||||||
, desi = {}
|
, desi = {/*TODO api_base: '/api'*/}
|
||||||
, fsapi = window.fsapi
|
, fsapi = window.fsapi
|
||||||
;
|
;
|
||||||
|
|
||||||
|
function getBlogdir () {
|
||||||
|
return $http.get('/api/fs/rootdir').then(function (resp) {
|
||||||
|
desi.blogdir = resp.data;
|
||||||
|
return resp.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getBlogdir();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
reset: function () {
|
reset: function () {
|
||||||
desi = {};
|
desi = {};
|
||||||
|
return getBlogdir();
|
||||||
}
|
}
|
||||||
, toDesiDate: Desi.toLocaleDate
|
, toDesiDate: Desi.toLocaleDate
|
||||||
, meta: function () {
|
, meta: function () {
|
||||||
|
|
2
desirae
2
desirae
|
@ -1 +1 @@
|
||||||
Subproject commit 3235b6c182a6cff73fc3a2482b347979ad126b01
|
Subproject commit 4b7106363794014edd7575a6892fae98c5f83d70
|
|
@ -0,0 +1,134 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var fsapi = require('./desirae/lib/fsapi').fsapi
|
||||||
|
, path = require('path')
|
||||||
|
;
|
||||||
|
|
||||||
|
module.exports.create = function (options) {
|
||||||
|
var restful = {}
|
||||||
|
;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Required for desirae
|
||||||
|
//
|
||||||
|
restful.walk = function (req, res, next) {
|
||||||
|
if (!(/^GET$/i.test(req.method) || /^GET$/i.test(req.query._method))) {
|
||||||
|
next();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var opts = {}
|
||||||
|
, dirnames = req.query.dir && [req.query.dir] || (req.query.dirs && req.query.dirs.split(/,/g)) || req.body.dirs
|
||||||
|
;
|
||||||
|
|
||||||
|
if (!dirnames || !dirnames.length) {
|
||||||
|
res.json({ error: "please specify GET w/ req.query.dir or POST w/ _method=GET&dirs=path/to/thing,..." });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dirnames.every(function (dirname) {
|
||||||
|
return 'string' === typeof dirname;
|
||||||
|
})) {
|
||||||
|
res.json({ error: "malformed request: " + JSON.stringify(dirnames) });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (req.query.excludes) {
|
||||||
|
opts.excludes = req.query.excludes.split(',');
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (req.query.extensions) {
|
||||||
|
opts.extensions = req.query.extensions.split(/,/g);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('true' === req.query.dotfiles) {
|
||||||
|
opts.dotfiles = true;
|
||||||
|
}
|
||||||
|
if ('false' === req.query.sha1sum) {
|
||||||
|
opts.sha1sum = false;
|
||||||
|
}
|
||||||
|
if ('true' === req.query.contents) {
|
||||||
|
opts.contents = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO opts.contents?
|
||||||
|
fsapi.walk.walkDirs(options.blogdir, dirnames, opts).then(function (stats) {
|
||||||
|
if (!req.body.dirs && !req.query.dirs) {
|
||||||
|
res.json(stats[dirnames[0]]);
|
||||||
|
} else {
|
||||||
|
res.json(stats);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
restful.getFiles = function (req, res, next) {
|
||||||
|
if (!(/^GET$/i.test(req.method) || /^GET$/i.test(req.query._method))) {
|
||||||
|
next();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var filepaths = req.query.path && [req.query.path] || (req.query.paths && req.query.paths.split(/,/g)) || req.body.paths
|
||||||
|
;
|
||||||
|
|
||||||
|
if (!filepaths || !filepaths.length) {
|
||||||
|
res.json({ error: "please specify GET w/ req.query.path or POST _method=GET&paths=path/to/thing,..." });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fsapi.getfs(options.blogdir, filepaths).then(function (files) {
|
||||||
|
if (!req.body.paths && !req.query.paths) {
|
||||||
|
res.json(files[0]);
|
||||||
|
} else {
|
||||||
|
res.send(files);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
restful.putFiles = function (req, res, next) {
|
||||||
|
if (!(/^POST|PUT$/i.test(req.method) || /^POST|PUT$/i.test(req.query._method))) {
|
||||||
|
next();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var opts = {}
|
||||||
|
, files = req.body.files
|
||||||
|
;
|
||||||
|
|
||||||
|
if (!files || !files.length) {
|
||||||
|
res.json({ error: "please specify POST w/ req.body.files" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.tmpdir = options.tmpdir;
|
||||||
|
return fsapi.putfs(options.blogdir, files, opts).then(function (results) {
|
||||||
|
res.json(results);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
restful.copy = function (req, res, next) {
|
||||||
|
if (!(/^POST|PUT$/i.test(req.method) || /^POST|PUT$/i.test(req.query._method))) {
|
||||||
|
next();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var opts = {}
|
||||||
|
, files = req.body.files
|
||||||
|
;
|
||||||
|
|
||||||
|
if ('object' !== typeof files || !Object.keys(files).length) {
|
||||||
|
res.json({ error: "please specify POST w/ req.body.files" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fsapi.copyfs(options.blogdir, files, opts).then(function (results) {
|
||||||
|
res.json(results);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//
|
||||||
|
// end Desirae API
|
||||||
|
//
|
||||||
|
|
||||||
|
return restful;
|
||||||
|
};
|
|
@ -6,6 +6,9 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
|
"bin": {
|
||||||
|
"deardesi": "bin/deardesi.js"
|
||||||
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/DearDesi/deardesi.git"
|
"url": "https://github.com/DearDesi/deardesi.git"
|
||||||
|
@ -35,6 +38,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bluebird": "^2.6.4",
|
"bluebird": "^2.6.4",
|
||||||
"body-parser": "^1.10.1",
|
"body-parser": "^1.10.1",
|
||||||
|
"cli": "^0.6.5",
|
||||||
"compression": "^1.3.0",
|
"compression": "^1.3.0",
|
||||||
"connect": "^3.3.4",
|
"connect": "^3.3.4",
|
||||||
"connect-query": "^0.2.0",
|
"connect-query": "^0.2.0",
|
||||||
|
|
175
server.js
175
server.js
|
@ -1,173 +1,66 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
require('require-yaml');
|
module.exports.create = function (options) {
|
||||||
|
var connect = require('connect')
|
||||||
var connect = require('connect')
|
|
||||||
//, PromiseA = require('bluebird').Promise
|
|
||||||
, query = require('connect-query')
|
, query = require('connect-query')
|
||||||
, bodyParser = require('body-parser')
|
, bodyParser = require('body-parser')
|
||||||
, serveStatic = require('serve-static')
|
, serveStatic = require('serve-static')
|
||||||
, send = require('connect-send-json')
|
, send = require('connect-send-json')
|
||||||
|
|
||||||
, app = connect()
|
|
||||||
, fsapi = require('./desirae/lib/fsapi')
|
|
||||||
, walk = require('./desirae/lib/fsapi').walk
|
|
||||||
, getfs = require('./desirae/lib/fsapi').getfs
|
|
||||||
, putfs = require('./desirae/lib/fsapi').putfs
|
|
||||||
|
|
||||||
, blogdir = process.argv[2]
|
|
||||||
, port = process.argv[3] || '65080'
|
|
||||||
|
|
||||||
, path = require('path')
|
, path = require('path')
|
||||||
//, config = require(path.join('./', blogdir, 'config.yml'))
|
|
||||||
|
, app = connect()
|
||||||
|
, restful = require('./desirae-http-api').create(options)
|
||||||
;
|
;
|
||||||
|
|
||||||
if (!blogdir) {
|
app
|
||||||
console.error("Usage: deardesi ~/path/to/blog");
|
|
||||||
process.exit(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
app
|
|
||||||
.use(send.json())
|
.use(send.json())
|
||||||
.use(query())
|
.use(query())
|
||||||
.use(bodyParser.json({ limit: 10 * 1024 * 1024 })) // 10mb
|
.use(bodyParser.json({ limit: 10 * 1024 * 1024 })) // 10mb
|
||||||
.use(require('compression')())
|
.use(require('compression')())
|
||||||
.use('/api/fs/walk', function (req, res, next) {
|
|
||||||
if (!(/^GET$/i.test(req.method) || /^GET$/i.test(req.query._method))) {
|
|
||||||
next();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var opts = {}
|
|
||||||
, dirnames = req.query.dir && [req.query.dir] || (req.query.dirs && req.query.dirs.split(/,/g)) || req.body.dirs
|
|
||||||
;
|
;
|
||||||
|
|
||||||
if (!dirnames || !dirnames.length) {
|
//
|
||||||
res.json({ error: "please specify GET w/ req.query.dir or POST w/ _method=GET&dirs=path/to/thing,..." });
|
// Keeping the API *required* by desirae super minimal
|
||||||
return;
|
// so that it can be implemented easily in any language
|
||||||
}
|
//
|
||||||
|
app
|
||||||
if (!dirnames.every(function (dirname) {
|
.use('/api/fs/static', serveStatic(options.blogdir))
|
||||||
return 'string' === typeof dirname;
|
.use('/api/fs/walk', restful.walk)
|
||||||
})) {
|
.use('/api/fs/files', restful.getFiles)
|
||||||
res.json({ error: "malformed request: " + JSON.stringify(dirnames) });
|
.use('/api/fs/files', restful.putFiles)
|
||||||
return;
|
.use('/api/fs/copy', restful.copy)
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (req.query.excludes) {
|
|
||||||
opts.excludes = req.query.excludes.split(',');
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (req.query.extensions) {
|
|
||||||
opts.extensions = req.query.extensions.split(/,/g);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('true' === req.query.dotfiles) {
|
|
||||||
opts.dotfiles = true;
|
|
||||||
}
|
|
||||||
if ('false' === req.query.sha1sum) {
|
|
||||||
opts.sha1sum = false;
|
|
||||||
}
|
|
||||||
if ('true' === req.query.contents) {
|
|
||||||
opts.contents = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO opts.contents?
|
|
||||||
walk.walkDirs(blogdir, dirnames, opts).then(function (stats) {
|
|
||||||
if (!req.body.dirs && !req.query.dirs) {
|
|
||||||
res.json(stats[dirnames[0]]);
|
|
||||||
} else {
|
|
||||||
res.json(stats);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.use('/api/fs/files', function (req, res, next) {
|
|
||||||
if (!(/^GET$/i.test(req.method) || /^GET$/i.test(req.query._method))) {
|
|
||||||
next();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var filepaths = req.query.path && [req.query.path] || (req.query.paths && req.query.paths.split(/,/g)) || req.body.paths
|
|
||||||
;
|
;
|
||||||
|
// end Desirae API
|
||||||
|
|
||||||
if (!filepaths || !filepaths.length) {
|
if (options.tmpdir) {
|
||||||
res.json({ error: "please specify GET w/ req.query.path or POST _method=GET&paths=path/to/thing,..." });
|
app.use(serveStatic(options.tmpdir));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return getfs(blogdir, filepaths).then(function (files) {
|
// this is used by DearDesi, but not required for desirae
|
||||||
if (!req.body.paths && !req.query.paths) {
|
app
|
||||||
res.json(files[0]);
|
.use('/api/fs/rootdir', function (req, res) {
|
||||||
} else {
|
var pathname = path.resolve(options.blogdir)
|
||||||
res.send(files);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.use('/api/fs/files', function (req, res, next) {
|
|
||||||
if (!(/^POST|PUT$/i.test(req.method) || /^POST|PUT$/i.test(req.query._method))) {
|
|
||||||
next();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var opts = {}
|
|
||||||
, files = req.body.files
|
|
||||||
;
|
|
||||||
|
|
||||||
if (!files || !files.length) {
|
|
||||||
res.json({ error: "please specify POST w/ req.body.files" });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return putfs(blogdir, files, opts).then(function (results) {
|
|
||||||
res.json(results);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.use('/api/fs/copy', function (req, res, next) {
|
|
||||||
if (!(/^POST|PUT$/i.test(req.method) || /^POST|PUT$/i.test(req.query._method))) {
|
|
||||||
next();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var opts = {}
|
|
||||||
, files = req.body.files
|
|
||||||
;
|
|
||||||
|
|
||||||
if ('object' !== typeof files || !Object.keys(files).length) {
|
|
||||||
res.json({ error: "please specify POST w/ req.body.files" });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fsapi.copyfs(blogdir, files, opts).then(function (results) {
|
|
||||||
res.json(results);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
|
|
||||||
.use('/api/fs', function (req, res) {
|
|
||||||
var pathname = path.resolve(blogdir)
|
|
||||||
;
|
;
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
path: pathname
|
path: pathname
|
||||||
, name: path.basename(pathname)
|
, name: path.basename(pathname)
|
||||||
, relativePath: path.dirname(pathname)
|
, relativePath: path.dirname(pathname)
|
||||||
//, cwd: path.resolve()
|
|
||||||
//, patharg: blogdir
|
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
})
|
})
|
||||||
.use('/api/fs/static', serveStatic(blogdir))
|
|
||||||
|
|
||||||
.use(serveStatic('./'))
|
|
||||||
.use('/compiled_dev', serveStatic(path.join(blogdir, '/compiled_dev')))
|
|
||||||
// TODO
|
|
||||||
//.use(serveStatic(tmpdir))
|
|
||||||
;
|
;
|
||||||
|
|
||||||
module.exports = app;
|
app
|
||||||
|
// the AngularJS App
|
||||||
|
.use(serveStatic(__dirname))
|
||||||
|
// TODO change file requests to '/blog'
|
||||||
|
//.use(serveStatic(options.blogdir))
|
||||||
|
.use('/blog', serveStatic(options.blogdir))
|
||||||
|
.use('/compiled_dev', serveStatic(path.join(options.blogdir, '/compiled_dev')))
|
||||||
|
//.use('/compiled', serveStatic(path.join(options.blogdir, '/compiled')))
|
||||||
|
;
|
||||||
|
|
||||||
require('http').createServer().on('request', app).listen(port, function () {
|
return app;
|
||||||
console.log('listening from ' + blogdir + ' http://local.dear.desi:' + port);
|
};
|
||||||
});
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h1>Write a Post</h1>
|
<h1>Write a Post</h1>
|
||||||
<h3><span ng-bind="Post.selected.abspath" ></span></h3>
|
<h3><span ng-bind="Post.selected.post.yml.permalink" ></span></h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -105,6 +105,22 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="inputPostAbsPath" class="col-lg-2 control-label">URL</label>
|
||||||
|
<div class="col-lg-10">
|
||||||
|
<input
|
||||||
|
required="required"
|
||||||
|
disabled
|
||||||
|
ng-model="Post.selected.url"
|
||||||
|
ng-change="Post.onChange()"
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="inputPostAbsPath"
|
||||||
|
placeholder="i.e. https://blog.me.co/posts/my-first-post/"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="inputPostAbsPath" class="col-lg-2 control-label">Filepath</label>
|
<label for="inputPostAbsPath" class="col-lg-2 control-label">Filepath</label>
|
||||||
<div class="col-lg-10">
|
<div class="col-lg-10">
|
||||||
|
|
|
@ -88,6 +88,8 @@ angular.module('myApp.post', ['ngRoute'])
|
||||||
if (!/\.html?$/.test(selected.path)) {
|
if (!/\.html?$/.test(selected.path)) {
|
||||||
selected.path = window.path.join(selected.path, 'index.html');
|
selected.path = window.path.join(selected.path, 'index.html');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selected.url = window.path.join(scope.site.base_url + window.path.join(scope.site.base_path, post.yml.permalink));
|
||||||
selected.abspath = window.path.join(scope.blogdir, selected.path);
|
selected.abspath = window.path.join(scope.blogdir, selected.path);
|
||||||
};
|
};
|
||||||
scope.onFrontmatterChange = function () {
|
scope.onFrontmatterChange = function () {
|
||||||
|
@ -107,10 +109,13 @@ angular.module('myApp.post', ['ngRoute'])
|
||||||
scope.selected.post.yml = data;
|
scope.selected.post.yml = data;
|
||||||
|
|
||||||
post = scope.selected.post;
|
post = scope.selected.post;
|
||||||
|
|
||||||
scope.selected.path = window.path.join((scope.selected.collection || 'posts'), window.path.basename(post.yml.permalink));
|
scope.selected.path = window.path.join((scope.selected.collection || 'posts'), window.path.basename(post.yml.permalink));
|
||||||
if (!/\.html?$/.test(scope.selected.path)) {
|
if (!/\.html?$/.test(window.path.basename(post.yml.permalink))) {
|
||||||
scope.selected.path = window.path.join(scope.selected.path, 'index.html');
|
scope.selected.path = window.path.join(scope.selected.path.replace(/\.w+$/, ''), 'index.html');
|
||||||
}
|
}
|
||||||
|
scope.selected.url = window.path.join(scope.site.base_url + window.path.join(scope.site.base_path, post.yml.permalink));
|
||||||
|
scope.selected.abspath = window.path.join(scope.blogdir, scope.selected.path);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
console.error('ignoring update that created parse error');
|
console.error('ignoring update that created parse error');
|
||||||
|
|
Loading…
Reference in New Issue