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:
parent
fbb0ac5892
commit
38e8a881d5
@ -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');
|
||||
|
@ -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');
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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 = {
|
||||
|
||||
|
43
ReactNativeClient/lib/renderers/HtmlToHtml.js
Normal file
43
ReactNativeClient/lib/renderers/HtmlToHtml.js
Normal 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;
|
35
ReactNativeClient/lib/renderers/MarkupToHtml.js
Normal file
35
ReactNativeClient/lib/renderers/MarkupToHtml.js
Normal 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;
|
@ -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'),
|
@ -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;
|
||||
|
@ -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');
|
||||
|
@ -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);
|
@ -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) {
|
@ -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>';
|
||||
|
@ -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) => {
|
||||
|
Loading…
Reference in New Issue
Block a user