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

Getting note HTML rendering to work

This commit is contained in:
Laurent Cozic 2017-11-05 16:51:03 +00:00
parent 09db5ff1d8
commit 3de7534d1d
8 changed files with 87 additions and 10 deletions

View File

@ -1,20 +1,49 @@
//const { BaseModel } = require('lib/base-model.js');
const React = require('react');
const { connect } = require('react-redux');
const { MdToHtml } = require('lib/markdown-utils.js');
class NoteTextComponent extends React.Component {
componentWillMount() {
this.mdToHtml_ = new MdToHtml();
this.setState({
note: null,
webviewReady: false,
});
}
componentDidMount() {
this.webview_.addEventListener('dom-ready', this.webview_domReady.bind(this));
}
componentWillUnmount() {
this.mdToHtml_ = null;
this.webview_.addEventListener('dom-ready', this.webview_domReady.bind(this));
}
componentWillReceiveProps(nextProps) {
if (nextProps.noteId) this.reloadNote();
}
webview_domReady() {
this.setState({
webviewReady: true,
});
this.webview_.openDevTools();
this.webview_.addEventListener('ipc-message', (event) => {
const msg = event.channel;
if (msg.indexOf('checkboxclick:') === 0) {
const newBody = this.mdToHtml_.handleCheckboxClick(msg, this.state.note.body);
// this.saveOneProperty('body', newBody);
//if (onCheckboxChange) onCheckboxChange(newBody);
}
})
}
async reloadNote() {
const note = this.props.noteId ? await Note.load(this.props.noteId) : null;
this.setState({
@ -26,9 +55,27 @@ class NoteTextComponent extends React.Component {
const note = this.state.note;
const body = note ? note.body : 'no note';
if (this.state.webviewReady) {
const mdOptions = {
onResourceLoaded: () => {
this.forceUpdate();
},
postMessageSyntax: 'ipcRenderer.sendToHost',
};
const html = this.mdToHtml_.render(note ? note.body : '', {}, mdOptions);
this.webview_.send('setHtml', html);
}
const webviewStyle = {
width: this.props.style.width,
height: this.props.style.height,
};
return (
<div style={this.props.style}>
{ body }
<webview style={webviewStyle} nodeintegration="1" src="note-content.html" ref={elem => this.webview_ = elem} />
</div>
);
}

View File

@ -0,0 +1,8 @@
<div id="content"></div>
<script>
const {ipcRenderer} = require('electron')
ipcRenderer.on('setHtml', (event, html) => {
document.getElementById('content').innerHTML = html;
});
</script>

View File

@ -2041,6 +2041,11 @@
"integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==",
"dev": true
},
"html-entities": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz",
"integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8="
},
"http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
@ -2604,6 +2609,11 @@
"integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
"dev": true
},
"marked": {
"version": "0.3.6",
"resolved": "https://registry.npmjs.org/marked/-/marked-0.3.6.tgz",
"integrity": "sha1-ssbGGPzOzk74bE/Gy4p8v1rtqNc="
},
"mem": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",

View File

@ -27,7 +27,9 @@
"dependencies": {
"app-module-path": "^2.2.0",
"fs-extra": "^4.0.2",
"html-entities": "^1.2.1",
"lodash": "^4.17.4",
"marked": "^0.3.6",
"moment": "^2.19.1",
"node-fetch": "^1.7.3",
"promise": "^8.0.1",

View File

@ -3,7 +3,7 @@ const { WebView, View, Linking } = require('react-native');
const { globalStyle } = require('lib/components/global-style.js');
const { Resource } = require('lib/models/resource.js');
const { reg } = require('lib/registry.js');
const { markdownUtils, MdToHtml } = require('lib/markdown-utils.js');
const { MdToHtml } = require('lib/markdown-utils.js');
class NoteBodyViewer extends Component {

View File

@ -9,12 +9,16 @@ class MdToHtml {
render(body, style, options = null) {
if (!options) options = {};
if (!options.postMessageSyntax) options.postMessageSyntax = 'postMessage';
// ipcRenderer.sendToHost('pong')
const { Resource } = require('lib/models/resource.js');
const Entities = require('html-entities').AllHtmlEntities;
const htmlentities = (new Entities()).encode;
const { shim } = require('lib/shim.js');
const loadResource = async function(id) {
const loadResource = async (id) => {
const resource = await Resource.load(id);
resource.base64 = await shim.readLocalFileBase64(Resource.fullPath(resource));
@ -91,7 +95,7 @@ class MdToHtml {
if (Resource.isResourceUrl(href)) {
return '[Resource not yet supported: ' + htmlentities(text) + ']';
} else {
const js = "postMessage(" + JSON.stringify(href) + "); return false;";
const js = options.postMessageSyntax + "(" + JSON.stringify(href) + "); return false;";
let output = "<a title='" + htmlentities(title) + "' href='#' onclick='" + js + "'>" + htmlentities(text) + '</a>';
return output;
}
@ -104,7 +108,7 @@ class MdToHtml {
const resourceId = Resource.urlToId(href);
if (!this.loadedResources_[resourceId]) {
this.loadResource(resourceId);
loadResource(resourceId);
return '';
}
@ -131,7 +135,7 @@ class MdToHtml {
let elementId = 1;
while (html.indexOf('°°JOP°') >= 0) {
html = html.replace(/°°JOP°CHECKBOX°([A-Z]+)°(\d+)°°/, function(v, type, index) {
const js = "postMessage('checkboxclick:" + type + ':' + index + "'); this.textContent = this.textContent == '☐' ? '☑' : '☐'; return false;";
const js = options.postMessageSyntax + "('checkboxclick:" + type + ':' + index + "'); this.textContent = this.textContent == '☐' ? '☑' : '☐'; return false;";
return '<a href="#" onclick="' + js + '" class="checkbox">' + (type == 'NOTICK' ? '☐' : '☑') + '</a>';
});
}
@ -139,7 +143,8 @@ class MdToHtml {
//let scriptHtml = '<script>document.body.scrollTop = ' + this.bodyScrollTop_ + ';</script>';
let scriptHtml = '';
html = '<body onscroll="postMessage(\'bodyscroll:\' + document.body.scrollTop);">' + html + scriptHtml + '</body>';
//html = '<body onscroll="postMessage(\'bodyscroll:\' + document.body.scrollTop);">' + html + scriptHtml + '</body>';
html = '<body>' + html + scriptHtml + '</body>';
return html;
}

View File

@ -55,6 +55,11 @@ function shimInit() {
const nodeFetch = require('node-fetch');
shim.readLocalFileBase64 = (path) => {
const data = fs.readFileSync(path);
return new Buffer(data).toString('base64');
}
shim.fetch = async function(url, options = null) {
if (!options) options = {};
if (!options.timeout) options.timeout = 1000 * 120; // ms

View File

@ -13,7 +13,7 @@ shim.fetch = typeof fetch !== 'undefined' ? fetch : null;
shim.FormData = typeof FormData !== 'undefined' ? FormData : null;
shim.fs = null;
shim.FileApiDriverLocal = null;
shim.readLocalFileBase64 = () => { throw new Error('Not implemented'); }
shim.readLocalFileBase64 = (path) => { throw new Error('Not implemented'); }
shim.uploadBlob = () => { throw new Error('Not implemented'); }
shim.setInterval = function(fn, interval) {
return setInterval(fn, interval);