You've already forked joplin
							
							
				mirror of
				https://github.com/laurent22/joplin.git
				synced 2025-10-31 00:07:48 +02:00 
			
		
		
		
	More refactoring to easily handle multiple renderers
This commit is contained in:
		| @@ -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) => { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user