1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00

More refactoring to easily handle multiple renderers

This commit is contained in:
Laurent Cozic 2019-07-16 19:05:47 +01:00
parent fbb0ac5892
commit 38e8a881d5
20 changed files with 115 additions and 29 deletions

View File

@ -47,7 +47,7 @@ convertJsx(__dirname + '/plugins');
const libContent = [
fs.readFileSync(basePath + '/ReactNativeClient/lib/string-utils-common.js', 'utf8'),
fs.readFileSync(basePath + '/ReactNativeClient/lib/markJsUtils.js', 'utf8'),
fs.readFileSync(basePath + '/ReactNativeClient/lib/MdToHtml/webviewLib.js', 'utf8'),
fs.readFileSync(basePath + '/ReactNativeClient/lib/renderers/webviewLib.js', 'utf8'),
];
fs.writeFileSync(__dirname + '/gui/note-viewer/lib.js', libContent.join('\n'), 'utf8');

View File

@ -9,7 +9,7 @@ const Revision = require('lib/models/Revision');
const Setting = require('lib/models/Setting');
const RevisionService = require('lib/services/RevisionService');
const shared = require('lib/components/shared/note-screen-shared.js');
const MdToHtml = require('lib/MdToHtml');
const MdToHtml = require('lib/renderers/MdToHtml');
const { time } = require('lib/time-utils.js');
const ReactTooltip = require('react-tooltip');
const { substrWithEllipsis } = require('lib/string-utils');

View File

@ -12,7 +12,7 @@ const TagList = require('./TagList.min.js');
const { connect } = require('react-redux');
const { _ } = require('lib/locale.js');
const { reg } = require('lib/registry.js');
const MdToHtml = require('lib/MdToHtml');
const MarkupToHtml = require('lib/renderers/MarkupToHtml');
const shared = require('lib/components/shared/note-screen-shared.js');
const { bridge } = require('electron').remote.require('./bridge');
const { themeStyle } = require('../theme.js');
@ -325,12 +325,12 @@ class NoteTextComponent extends React.Component {
}
}
mdToHtml() {
if (this.mdToHtml_) return this.mdToHtml_;
this.mdToHtml_ = new MdToHtml({
markupToHtml() {
if (this.markupToHtml_) return this.markupToHtml_;
this.markupToHtml_ = new MarkupToHtml({
resourceBaseUrl: 'file://' + Setting.value('resourceDir') + '/',
});
return this.mdToHtml_;
return this.markupToHtml_;
}
async componentWillMount() {
@ -355,7 +355,7 @@ class NoteTextComponent extends React.Component {
this.lastLoadedNoteId_ = note ? note.id : null;
this.updateHtml(note && note.body ? note.body : '');
this.updateHtml(note ? note.markup_language : null, note && note.body ? note.body : '');
eventManager.on('alarmChange', this.onAlarmChange_);
eventManager.on('noteTypeToggle', this.onNoteTypeToggle_);
@ -369,7 +369,7 @@ class NoteTextComponent extends React.Component {
componentWillUnmount() {
this.saveIfNeeded();
this.mdToHtml_ = null;
this.markupToHtml_ = null;
eventManager.removeListener('alarmChange', this.onAlarmChange_);
eventManager.removeListener('noteTypeToggle', this.onNoteTypeToggle_);
@ -481,7 +481,7 @@ class NoteTextComponent extends React.Component {
}
}
this.mdToHtml_ = null;
this.markupToHtml_ = null;
// If we are loading nothing (noteId == null), make sure to
// set webviewReady to false too because the webview component
@ -595,7 +595,7 @@ class NoteTextComponent extends React.Component {
// if (newState.note) await shared.refreshAttachedResources(this, newState.note.body);
this.updateHtml(newState.note ? newState.note.body : '');
this.updateHtml(newState.note ? newState.note.markup_language : null, newState.note ? newState.note.body : '');
}
async componentWillReceiveProps(nextProps) {
@ -930,12 +930,20 @@ class NoteTextComponent extends React.Component {
}
}
async updateHtml(body = null, options = null) {
async updateHtml(markupLanguage = null, body = null, options = null) {
if (!options) options = {};
if (!('useCustomCss' in options)) options.useCustomCss = true;
let bodyToRender = body;
if (bodyToRender === null) bodyToRender = this.state.note && this.state.note.body ? this.state.note.body : '';
if (bodyToRender === null) {
bodyToRender = this.state.note && this.state.note.body ? this.state.note.body : '';
markupLanguage = this.state.note ? this.state.note.markup_language : Note.MARKUP_LANGUAGE_MARKDOWN;
}
if (!markupLanguage) markupLanguage = Note.MARKUP_LANGUAGE_MARKDOWN;
const resources = await shared.attachedResources(bodyToRender);
const theme = themeStyle(this.props.theme);
@ -943,7 +951,7 @@ class NoteTextComponent extends React.Component {
codeTheme: theme.codeThemeCss,
postMessageSyntax: 'ipcProxySendToHost',
userCss: options.useCustomCss ? this.props.customCss : '',
resources: await shared.attachedResources(bodyToRender),
resources: resources,
codeHighlightCacheKey: this.state.note ? this.state.note.id : null,
};
@ -953,10 +961,10 @@ class NoteTextComponent extends React.Component {
if (!bodyToRender.trim() && visiblePanes.indexOf('viewer') >= 0 && visiblePanes.indexOf('editor') < 0) {
// Fixes https://github.com/laurent22/joplin/issues/217
bodyToRender = '*' + _('This note has no content. Click on "%s" to toggle the editor and edit the note.', _('Layout')) + '*';
bodyToRender = '<i>' + _('This note has no content. Click on "%s" to toggle the editor and edit the note.', _('Layout')) + '</i>';
}
const result = this.mdToHtml().render(bodyToRender, theme, mdOptions);
const result = this.markupToHtml().render(markupLanguage, bodyToRender, theme, mdOptions);
this.setState({
bodyHtml: result.html,
@ -1079,7 +1087,7 @@ class NoteTextComponent extends React.Component {
lastSavedNote: Object.assign({}, note),
});
this.updateHtml(note.body);
this.updateHtml(note.markup_language, note.body);
} catch (error) {
reg.logger().error(error);
bridge().showErrorMessageBox(error.message);
@ -1108,13 +1116,13 @@ class NoteTextComponent extends React.Component {
const previousTheme = Setting.value('theme');
Setting.setValue('theme', Setting.THEME_LIGHT);
this.lastSetHtml_ = '';
await this.updateHtml(tempBody, { useCustomCss: false });
await this.updateHtml(this.state.note.markup_language, tempBody, { useCustomCss: false });
this.forceUpdate();
const restoreSettings = async () => {
Setting.setValue('theme', previousTheme);
this.lastSetHtml_ = '';
await this.updateHtml(previousBody);
await this.updateHtml(this.state.note.markup_language, previousBody);
this.forceUpdate();
}

View File

@ -6,7 +6,7 @@ const Resource = require('lib/models/Resource.js');
const Setting = require('lib/models/Setting.js');
const { reg } = require('lib/registry.js');
const { shim } = require('lib/shim');
const MdToHtml = require('lib/MdToHtml.js');
const MdToHtml = require('lib/renderers/MdToHtml.js');
const shared = require('lib/components/shared/note-screen-shared.js');
class NoteBodyViewer extends Component {

View File

@ -1,7 +1,7 @@
const stringPadding = require('string-padding');
const urlUtils = require('lib/urlUtils');
const MarkdownIt = require('markdown-it');
const setupLinkify = require('lib/MdToHtml/setupLinkify');
const setupLinkify = require('lib/renderers/MdToHtml/setupLinkify');
const markdownUtils = {

View File

@ -0,0 +1,43 @@
const Resource = require('lib/models/Resource');
const htmlUtils = require('lib/htmlUtils');
const utils = require('./utils');
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
class HtmlToHtml {
constructor(options) {
this.resourceBaseUrl_ = 'resourceBaseUrl' in options ? options.resourceBaseUrl : null;
}
render(markup, theme, options) {
const dom = new JSDOM(markup);
// Replace all the image resource IDs by path to local files
const imgs = dom.window.document.getElementsByTagName('img');
for (const img of imgs) {
if (!img.src) continue;
const r = utils.imageReplacement(img.src, options.resources, this.resourceBaseUrl_);
if (!r) continue;
if (typeof r === 'string') {
img.outerHTML = r;
} else {
for (const n in r) {
img.setAttribute(n, r[n]);
}
}
}
// We need this extra style so that the images don't overflow
const extraStyle = '<style>img {max-width: 100%;height: auto;}</style>'
return {
html: extraStyle + htmlUtils.headAndBodyHtml(dom.window.document),
cssFiles: [],
}
}
}
module.exports = HtmlToHtml;

View File

@ -0,0 +1,35 @@
const MdToHtml = require('./MdToHtml');
const HtmlToHtml = require('./HtmlToHtml');
const Note = require('lib/models/Note');
class MarkupToHtml {
constructor(options) {
this.options_ = options;
this.renderers_ = {};
}
renderer(markupLanguage) {
if (this.renderers_[markupLanguage]) return this.renderers_[markupLanguage];
let RendererClass = null;
if (markupLanguage === Note.MARKUP_LANGUAGE_MARKDOWN) {
RendererClass = MdToHtml;
} else if (markupLanguage === Note.MARKUP_LANGUAGE_HTML) {
RendererClass = HtmlToHtml;
} else {
throw new Error('Invalid markup language: ' + markupLanguage);
}
this.renderers_[markupLanguage] = new RendererClass(this.options_);
return this.renderers_[markupLanguage];
}
render(markupLanguage, markup, theme, options) {
return this.renderer(markupLanguage).render(markup, theme, options);
}
}
module.exports = MarkupToHtml;

View File

@ -6,8 +6,8 @@ const { shim } = require('lib/shim.js');
const { _ } = require('lib/locale');
const md5 = require('md5');
const StringUtils = require('lib/string-utils.js');
const noteStyle = require('./MdToHtml/noteStyle');
const Setting = require('./models/Setting.js');
const noteStyle = require('./noteStyle');
const Setting = require('lib/models/Setting.js');
const rules = {
image: require('./MdToHtml/rules/image'),
checkbox: require('./MdToHtml/rules/checkbox'),

View File

@ -1,7 +1,7 @@
const Entities = require('html-entities').AllHtmlEntities;
const htmlentities = (new Entities()).encode;
const Resource = require('lib/models/Resource.js');
const utils = require('../utils');
const utils = require('../../utils');
let checkboxIndex_ = -1;

View File

@ -1,7 +1,7 @@
const Entities = require('html-entities').AllHtmlEntities;
const htmlentities = (new Entities()).encode;
const Resource = require('lib/models/Resource.js');
const utils = require('../utils');
const utils = require('../../utils');
const StringUtils = require('lib/string-utils.js');
const md5 = require('md5');

View File

@ -2,7 +2,7 @@ const Entities = require('html-entities').AllHtmlEntities;
const htmlentities = (new Entities()).encode;
const Resource = require('lib/models/Resource.js');
const htmlUtils = require('lib/htmlUtils.js');
const utils = require('../utils');
const utils = require('../../utils');
function renderImageHtml(before, src, after, ruleOptions) {
const r = utils.imageReplacement(src, ruleOptions.resources, ruleOptions.resourceBaseUrl);

View File

@ -1,7 +1,7 @@
const Entities = require('html-entities').AllHtmlEntities;
const htmlentities = (new Entities()).encode;
const Resource = require('lib/models/Resource.js');
const utils = require('../utils');
const utils = require('../../utils');
const htmlUtils = require('lib/htmlUtils.js');
function installRule(markdownIt, mdOptions, ruleOptions) {

View File

@ -1,7 +1,7 @@
const Entities = require('html-entities').AllHtmlEntities;
const htmlentities = (new Entities()).encode;
const Resource = require('lib/models/Resource.js');
const utils = require('../utils');
const utils = require('../../utils');
const loaderImage = '<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0" width="16px" height="16px" viewBox="0 0 128 128" xml:space="preserve"><g><circle cx="16" cy="64" r="16" fill="#000000" fill-opacity="1"/><circle cx="16" cy="64" r="16" fill="#555555" fill-opacity="0.67" transform="rotate(45,64,64)"/><circle cx="16" cy="64" r="16" fill="#949494" fill-opacity="0.42" transform="rotate(90,64,64)"/><circle cx="16" cy="64" r="16" fill="#cccccc" fill-opacity="0.2" transform="rotate(135,64,64)"/><circle cx="16" cy="64" r="16" fill="#e1e1e1" fill-opacity="0.12" transform="rotate(180,64,64)"/><circle cx="16" cy="64" r="16" fill="#e1e1e1" fill-opacity="0.12" transform="rotate(225,64,64)"/><circle cx="16" cy="64" r="16" fill="#e1e1e1" fill-opacity="0.12" transform="rotate(270,64,64)"/><circle cx="16" cy="64" r="16" fill="#e1e1e1" fill-opacity="0.12" transform="rotate(315,64,64)"/><animateTransform attributeName="transform" type="rotate" values="0 64 64;315 64 64;270 64 64;225 64 64;180 64 64;135 64 64;90 64 64;45 64 64" calcMode="discrete" dur="720ms" repeatCount="indefinite"></animateTransform></g></svg>';

View File

@ -18,7 +18,7 @@ async function copyJs(name, filePath) {
async function main(argv) {
await fs.mkdirp(outputDir);
await copyJs('webviewLib', rnDir + '/lib/MdToHtml/webviewLib.js');
await copyJs('webviewLib', rnDir + '/lib/renderers/MdToHtml/webviewLib.js');
}
main(process.argv).catch((error) => {