diff --git a/ElectronClient/app/gui/NoteText.jsx b/ElectronClient/app/gui/NoteText.jsx
index 49f8bae845..4143afd93f 100644
--- a/ElectronClient/app/gui/NoteText.jsx
+++ b/ElectronClient/app/gui/NoteText.jsx
@@ -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 (
- { body }
+ this.webview_ = elem} />
);
}
diff --git a/ElectronClient/app/note-content.html b/ElectronClient/app/note-content.html
new file mode 100644
index 0000000000..a2bc264602
--- /dev/null
+++ b/ElectronClient/app/note-content.html
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/ElectronClient/app/package-lock.json b/ElectronClient/app/package-lock.json
index cb170fea40..9188d3532f 100644
--- a/ElectronClient/app/package-lock.json
+++ b/ElectronClient/app/package-lock.json
@@ -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",
diff --git a/ElectronClient/app/package.json b/ElectronClient/app/package.json
index 51915cb17c..5bf9cf06e8 100644
--- a/ElectronClient/app/package.json
+++ b/ElectronClient/app/package.json
@@ -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",
diff --git a/ReactNativeClient/lib/components/note-body-viewer.js b/ReactNativeClient/lib/components/note-body-viewer.js
index 587da735ea..93ec92547e 100644
--- a/ReactNativeClient/lib/components/note-body-viewer.js
+++ b/ReactNativeClient/lib/components/note-body-viewer.js
@@ -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 {
diff --git a/ReactNativeClient/lib/markdown-utils.js b/ReactNativeClient/lib/markdown-utils.js
index 53549467d9..ea7ccf7dd2 100644
--- a/ReactNativeClient/lib/markdown-utils.js
+++ b/ReactNativeClient/lib/markdown-utils.js
@@ -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 = "" + htmlentities(text) + '';
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 '' + (type == 'NOTICK' ? '☐' : '☑') + '';
});
}
@@ -139,7 +143,8 @@ class MdToHtml {
//let scriptHtml = '';
let scriptHtml = '';
- html = '' + html + scriptHtml + '';
+ //html = '' + html + scriptHtml + '';
+ html = '' + html + scriptHtml + '';
return html;
}
diff --git a/ReactNativeClient/lib/shim-init-node.js b/ReactNativeClient/lib/shim-init-node.js
index 5c69614808..2633a3335a 100644
--- a/ReactNativeClient/lib/shim-init-node.js
+++ b/ReactNativeClient/lib/shim-init-node.js
@@ -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
diff --git a/ReactNativeClient/lib/shim.js b/ReactNativeClient/lib/shim.js
index ed747930cf..d812aae637 100644
--- a/ReactNativeClient/lib/shim.js
+++ b/ReactNativeClient/lib/shim.js
@@ -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);