Removed ghost editor dependency (#8137)

refs #7429
- ☢️ 👷🏻‍♀️ This PR removes the dependency on Ghost-Editor and replaces it with the Mobiledoc DOM renderer. It includes new DOM based default cards and atoms.
This commit is contained in:
Ryan McCarvill 2017-03-15 07:07:33 +13:00 committed by Kevin Ansfield
parent 8382be1ada
commit f61aa662c1
20 changed files with 295 additions and 726 deletions

View File

@ -0,0 +1,3 @@
var softReturn = require('./soft-return');
module.exports = [softReturn];

View File

@ -0,0 +1,7 @@
module.exports = {
name: 'soft-return',
type: 'dom',
render(opts) {
return opts.env.dom.createElement('br');
}
};

View File

@ -0,0 +1,7 @@
module.exports = {
name: 'hr-card',
type: 'dom',
render(opts) {
return opts.env.dom.createElement('hr');
}
};

View File

@ -0,0 +1,12 @@
var SimpleDom = require('simple-dom'),
tokenizer = require('simple-html-tokenizer').tokenize,
parser;
module.exports = {
name: 'html-card',
type: 'dom',
render(opts) {
parser = new SimpleDom.HTMLParser(tokenizer, opts.env.dom, SimpleDom.voidMap);
return parser.parse('<div>' + opts.payload.html + '</div>');
}
};

View File

@ -0,0 +1,9 @@
module.exports = {
name: 'image-card',
type: 'dom',
render(opts) {
var img = opts.env.dom.createElement('img');
img.setAttribute('src', opts.payload.img);
return img;
}
};

View File

@ -0,0 +1,6 @@
var hr = require('./hr'),
html = require('./html'),
image = require('./image'),
markdown = require('./markdown');
module.exports = [hr, html, image, markdown];

View File

@ -0,0 +1,14 @@
var SimpleDom = require('simple-dom'),
tokenizer = require('simple-html-tokenizer').tokenize,
Showdown = require('showdown-ghost'),
converter = new Showdown.converter({extensions: ['ghostgfm', 'footnotes', 'highlight']}),
parser;
module.exports = {
name: 'markdown-card',
type: 'dom',
render(opts) {
parser = new SimpleDom.HTMLParser(tokenizer, opts.env.dom, SimpleDom.voidMap);
return parser.parse('<div>' + converter.makeHtml(opts.payload.markdown || '') + '</div>');
}
};

View File

@ -0,0 +1,9 @@
var cards = require('./cards'),
atoms = require('./atoms');
module.exports = {
cards: cards,
atoms: atoms,
activate: function () {
// needed by ghost
}
};

View File

@ -0,0 +1,18 @@
var should = require('should'),
card = require('../cards/hr'),
SimpleDom = require('simple-dom'),
opts;
should = should;
describe('HR card', function () {
it('generates a horizontal rule', function () {
opts = {
env: {
dom: new SimpleDom.Document()
}
};
var serializer = new SimpleDom.HTMLSerializer([]);
serializer.serialize(card.render(opts)).should.match('<hr></hr>');
});
});

View File

@ -0,0 +1,47 @@
var should = require('should'),
card = require('../cards/html'),
SimpleDom = require('simple-dom'),
opts;
should = should;
describe('HTML card', function () {
it('HTML Card renders', function () {
opts = {
env: {
dom: new SimpleDom.Document()
},
payload: {
html: '<h1>HEADING</h1><p>PARAGRAPH</p>'
}
};
var serializer = new SimpleDom.HTMLSerializer([]);
serializer.serialize(card.render(opts)).should.match('<div><h1>HEADING</h1><p>PARAGRAPH</p></div>');
});
it('Plain content renders', function () {
opts = {
env: {
dom: new SimpleDom.Document()
},
payload: {
html: 'CONTENT'
}
};
var serializer = new SimpleDom.HTMLSerializer([]);
serializer.serialize(card.render(opts)).should.match('<div>CONTENT</div>');
});
it.skip('Invalid HTML returns', function () {
opts = {
env: {
dom: new SimpleDom.Document()
},
payload: {
html: '<h1>HEADING<'
}
};
var serializer = new SimpleDom.HTMLSerializer([]);
serializer.serialize(card.render(opts)).should.match('<div><h1>HEADING<</div>');
});
});

View File

@ -0,0 +1,21 @@
var should = require('should'),
card = require('../cards/image'),
SimpleDom = require('simple-dom'),
opts;
should = should;
describe('Image card', function () {
it('generates an image', function () {
opts = {
env: {
dom: new SimpleDom.Document()
},
payload: {
img: 'https://www.ghost.org/image.png'
}
};
var serializer = new SimpleDom.HTMLSerializer([]);
serializer.serialize(card.render(opts)).should.match('<img src="https://www.ghost.org/image.png"></img>');
});
});

View File

@ -0,0 +1,21 @@
var should = require('should'),
card = require('../cards/markdown'),
SimpleDom = require('simple-dom'),
opts;
should = should;
describe('Markdown card', function () {
it('Markdown Card renders', function () {
opts = {
env: {
dom: new SimpleDom.Document()
},
payload: {
markdown: '#HEADING\r\n- list\r\n- items'
}
};
var serializer = new SimpleDom.HTMLSerializer([]);
serializer.serialize(card.render(opts)).should.match('<div><h1 id="heading">HEADING</h1>\n\n<ul>\n<li>list</li>\n<li>items</li>\n</ul></div>');
});
});

View File

@ -0,0 +1,18 @@
var should = require('should'),
card = require('../atoms/soft-return'),
SimpleDom = require('simple-dom'),
opts;
should = should;
describe('Soft return card', function () {
it('generates a `br` tag', function () {
opts = {
env: {
dom: new SimpleDom.Document()
}
};
var serializer = new SimpleDom.HTMLSerializer([]);
serializer.serialize(card.render(opts)).should.match('<br></br>');
});
});

View File

@ -14,7 +14,8 @@
"internalApps": [
"private-blogging",
"subscribers",
"amp"
"amp",
"default-cards"
],
"routeKeywords": {
"tag": "tag",

View File

@ -7,9 +7,6 @@ var _ = require('lodash'),
errors = require('../errors'),
Showdown = require('showdown-ghost'),
legacyConverter = new Showdown.converter({extensions: ['ghostgfm', 'footnotes', 'highlight']}),
Mobiledoc = require('mobiledoc-html-renderer').default,
mobileDocOptions = require('ghost-editor').htmlOptions,
converter = new Mobiledoc(mobileDocOptions),
ghostBookshelf = require('./base'),
events = require('../events'),
config = require('../config'),
@ -204,7 +201,7 @@ Post = ghostBookshelf.Model.extend({
ghostBookshelf.Model.prototype.onSaving.call(this, model, attr, options);
if (mobiledoc) {
this.set('html', converter.render(JSON.parse(mobiledoc)).result);
this.set('html', utils.mobiledocConverter.render(JSON.parse(mobiledoc)));
} else {
// legacy showdown mode
this.set('html', legacyConverter.makeHtml(_.toString(this.get('markdown'))));

View File

@ -111,7 +111,8 @@ utils = {
url: require('./url'),
tokens: require('./tokens'),
sequence: require('./sequence'),
ghostVersion: require('./ghost-version')
ghostVersion: require('./ghost-version'),
mobiledocConverter: require('./mobiledoc-converter')
};
module.exports = utils;

View File

@ -0,0 +1,40 @@
var SimpleDom = require('simple-dom'),
Renderer = require('mobiledoc-dom-renderer').default,
config = require('../config'),
defaults = require(config.get('paths').internalAppPath + 'default-cards'),
options = {
dom: new SimpleDom.Document(),
cards: defaults.cards,
atoms: defaults.atoms
};
// function getCards() {
// return config.get('internalApps').reduce(
// function (cards, appName) {
// var app = require(path.join(config.get('paths').internalAppPath, appName));
// if (app.hasOwnProperty('cards')) {
// cards = cards.concat(app.cards);
// }
// return cards;
// }, [ ]);
// }
// function getAtoms() {
// return config.get('internalApps').reduce(
// function (atoms, appName) {
// var app = require(path.join(config.get('paths').internalAppPath, appName));
// if (app.hasOwnProperty('atoms')) {
// atoms = atoms.concat(app.atoms);
// }
// return atoms;
// }, [ ]);
// }
module.exports = {
render: function (mobiledoc) {
var renderer = new Renderer(options),
rendered = renderer.render(mobiledoc),
serializer = new SimpleDom.HTMLSerializer([]),
html = serializer.serializeChildren(rendered.result);
return html;
}
};

View File

@ -0,0 +1,31 @@
var converter = require('../../../server/utils/mobiledoc-converter');
describe('Convert mobiledoc to HTML ', function () {
var mobiledoc = {
version: '0.3.1',
atoms: [],
cards: [
['markdown-card',
{
pos: 'top',
card_name: 'markdown-card',
markdown: '#heading\n\n- list one\n- list two\n- list three'
}
],
['markdown-card', {
pos: 'top'
}]
],
markups: [],
sections: [
[1, 'p', [
[0, [], 0, 'test']
]],
[10, 0],
[10, 1]
]
};
it('Converts a mobiledoc to HTML', function () {
converter.render(mobiledoc).should.match('<p>test</p><div><h1 id="heading">heading</h1>\n\n<ul>\n<li>list one</li>\n<li>list two</li>\n<li>list three</li>\n</ul></div><div></div>');
});
});

View File

@ -47,7 +47,6 @@
"express-hbs": "1.0.4",
"extract-zip-fork": "1.5.1",
"fs-extra": "2.0.0",
"ghost-editor": "0.1.10",
"ghost-gql": "0.0.6",
"ghost-ignition": "2.8.9",
"glob": "5.0.15",
@ -61,7 +60,7 @@
"knex": "0.12.7",
"knex-migrator": "2.0.13",
"lodash": "4.17.4",
"mobiledoc-html-renderer": "0.3.1",
"mobiledoc-dom-renderer": "0.6.5",
"moment": "2.17.1",
"moment-timezone": "0.5.9",
"multer": "1.3.0",
@ -79,6 +78,8 @@
"sanitize-html": "1.14.1",
"semver": "5.3.0",
"showdown-ghost": "0.3.6",
"simple-dom": "0.3.2",
"simple-html-tokenizer": "0.4.0",
"superagent": "3.5.0",
"unidecode": "0.1.8",
"uuid": "3.0.0",

742
yarn.lock

File diff suppressed because it is too large Load Diff