diff --git a/CliClient/package-lock.json b/CliClient/package-lock.json index d8ec10ebb..ff783047e 100644 --- a/CliClient/package-lock.json +++ b/CliClient/package-lock.json @@ -20,18 +20,18 @@ "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==" }, "acorn-globals": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.0.tgz", - "integrity": "sha512-hMtHj3s5RnuhvHPowpBYvJVj3rAar82JiDQHvGs1zO0l10ocX/xEdBShNHTJaboucJUsScghp74pH3s7EnHHQw==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.2.tgz", + "integrity": "sha512-BbzvZhVtZP+Bs1J1HcwrQe8ycfO0wStkSGxuul3He3GkHOIZ6eTqOkPuw9IP1X3+IkOo4wiJmwkobzXYz4wewQ==", "requires": { "acorn": "^6.0.1", "acorn-walk": "^6.0.1" }, "dependencies": { "acorn": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.6.tgz", - "integrity": "sha512-5M3G/A4uBSMIlfJ+h9W125vJvPFH/zirISsW5qfxF5YzEvXJCtolLoQvM5yZft0DvMcUrPGKPOlgEu55I6iUtA==" + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", + "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==" } } }, @@ -454,14 +454,14 @@ } }, "cssom": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.4.tgz", - "integrity": "sha512-+7prCSORpXNeR4/fUP3rL+TzqtiFfhMvTd7uEqMdgPvLPt4+uzFUeufx5RHjGTACCargg/DiEt/moMQmvnfkog==" + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.6.tgz", + "integrity": "sha512-DtUeseGk9/GBW0hl0vVPpU22iHL6YB5BUX7ml1hB+GMpo0NX5G4voX3kdWiMSEguFtcW3Vh3djqNF4aIe6ne0A==" }, "cssstyle": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.1.1.tgz", - "integrity": "sha512-364AI1l/M5TYcFH83JnOH/pSqgaNnKmYgKrm0didZMGKWjQB60dymwWy1rKUgL3J1ffdq9xVi2yGLHdSjjSNog==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.2.2.tgz", + "integrity": "sha512-43wY3kl1CVQSvL7wUY1qXkxVGkStjpkDmVjiIKX8R97uhajy8Bybay78uOtqvh7Q5GK75dNPfW0geWjE6qQQow==", "requires": { "cssom": "0.3.x" } @@ -661,9 +661,9 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "escodegen": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz", - "integrity": "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", + "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", "requires": { "esprima": "^3.1.3", "estraverse": "^4.2.0", @@ -1437,10 +1437,11 @@ "dev": true }, "joplin-turndown": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/joplin-turndown/-/joplin-turndown-4.0.11.tgz", - "integrity": "sha512-2oiwWX0nKYi1NVcaprSsrXQkYdGoRtPWFmnXdWQnQW44jlgjFV38B4VrgliwX5ZMq7cbx6A9IBwfXcBL2YV2NA==", + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/joplin-turndown/-/joplin-turndown-4.0.12.tgz", + "integrity": "sha512-HlxkcIiNFSMLBvYktoXqLLHFGuwQYlcPclo0Peeatw3cPe6iFqSsEgEGY/0bYM/fubA/zpPULrJcjST99BO9wQ==", "requires": { + "html-entities": "^1.2.1", "jsdom": "^11.9.0" } }, @@ -1499,9 +1500,9 @@ }, "dependencies": { "ajv": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", - "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", + "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", "requires": { "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", @@ -1515,9 +1516,9 @@ "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, "combined-stream": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", - "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "requires": { "delayed-stream": "~1.0.0" } @@ -1557,16 +1558,16 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "mime-db": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", - "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" }, "mime-types": { - "version": "2.1.21", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", - "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", "requires": { - "mime-db": "~1.37.0" + "mime-db": "1.40.0" } }, "oauth-sign": { @@ -2030,9 +2031,9 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "nwsapi": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.0.9.tgz", - "integrity": "sha512-nlWFSCTYQcHk/6A9FFnfhKc14c3aFhfdNBXgo8Qgi9QTBu/qg3Ww+Uiz9wMzXd1T8GFxPc2QIHB6Qtf2XFryFQ==" + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.4.tgz", + "integrity": "sha512-iGfd9Y6SFdTNldEy2L0GUhcarIutFmk+MPWIn9dmj8NMIup03G08uUF2KGbbmv/Ux4RT0VZJoP/sVbWA6d/VIw==" }, "oauth-sign": { "version": "0.8.2", @@ -2411,21 +2412,28 @@ } }, "request-promise-core": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", - "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", + "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", "requires": { - "lodash": "^4.13.1" + "lodash": "^4.17.11" + }, + "dependencies": { + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + } } }, "request-promise-native": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz", - "integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", + "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==", "requires": { - "request-promise-core": "1.1.1", - "stealthy-require": "^1.1.0", - "tough-cookie": ">=2.3.3" + "request-promise-core": "1.1.2", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" } }, "requires-port": { @@ -2852,9 +2860,9 @@ "integrity": "sha1-Kb9hXUqnEhvdiYsi1LP5vE4qoD0=" }, "symbol-tree": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", - "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=" + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, "syswide-cas": { "version": "5.2.0", diff --git a/CliClient/package.json b/CliClient/package.json index 526e9dfdd..b44d9c070 100644 --- a/CliClient/package.json +++ b/CliClient/package.json @@ -43,7 +43,7 @@ "html-minifier": "^3.5.15", "image-data-uri": "^2.0.0", "image-type": "^3.0.0", - "joplin-turndown": "^4.0.11", + "joplin-turndown": "^4.0.12", "joplin-turndown-plugin-gfm": "^1.0.8", "jssha": "^2.3.0", "levenshtein": "^1.0.5", diff --git a/CliClient/tests/HtmlToMd.js b/CliClient/tests/HtmlToMd.js index 8eb9ae7ee..dd4a55e9b 100644 --- a/CliClient/tests/HtmlToMd.js +++ b/CliClient/tests/HtmlToMd.js @@ -37,12 +37,22 @@ describe('HtmlToMd', function() { const htmlPath = basePath + '/' + htmlFilename; const mdPath = basePath + '/' + filename(htmlFilename) + '.md'; - // if (htmlFilename !== 'picture.html') continue; + // if (htmlFilename !== 'anchor_local.html') continue; + + const htmlToMdOptions = {} + + if (htmlFilename === 'anchor_local.html') { + // Normally the list of anchor names in the document are retrieved from the HTML code + // This is straightforward when the document is still in DOM format, as with the clipper, + // but otherwise it would need to be somehow parsed out from the HTML. Here we just + // hard code the anchors that we know are in the file. + htmlToMdOptions.anchorNames = ['first', 'second'] + } const html = await shim.fsDriver().readFile(htmlPath); let expectedMd = await shim.fsDriver().readFile(mdPath); - let actualMd = await htmlToMd.parse('
' + html + '
', []); + let actualMd = await htmlToMd.parse('
' + html + '
', htmlToMdOptions); if (os.EOL === '\r\n') { expectedMd = expectedMd.replace(/\r\n/g, '\n') diff --git a/CliClient/tests/html_to_md/anchor_local.html b/CliClient/tests/html_to_md/anchor_local.html new file mode 100644 index 000000000..67c35c5d9 --- /dev/null +++ b/CliClient/tests/html_to_md/anchor_local.html @@ -0,0 +1,6 @@ +

First

+

Second

+

Third

+

First

+

Second

+

Third

\ No newline at end of file diff --git a/CliClient/tests/html_to_md/anchor_local.md b/CliClient/tests/html_to_md/anchor_local.md new file mode 100644 index 000000000..0c68275df --- /dev/null +++ b/CliClient/tests/html_to_md/anchor_local.md @@ -0,0 +1,11 @@ +[First](#first) + +[Second](#second) + +Third + +First + +Second + +Third \ No newline at end of file diff --git a/CliClient/tests/html_to_md/anchor_with_js.md b/CliClient/tests/html_to_md/anchor_with_js.md index a1584d3d7..9dbfeeee5 100644 --- a/CliClient/tests/html_to_md/anchor_with_js.md +++ b/CliClient/tests/html_to_md/anchor_with_js.md @@ -1 +1 @@ -[Some text]() \ No newline at end of file +Some text \ No newline at end of file diff --git a/CliClient/tests/urlUtils.js b/CliClient/tests/urlUtils.js index 6c38b7d1c..5d910c456 100644 --- a/CliClient/tests/urlUtils.js +++ b/CliClient/tests/urlUtils.js @@ -30,6 +30,7 @@ describe('urlUtils', function() { expect(urlUtils.prependBaseUrl('mailto:emailme@example.com', 'http://example.com')).toBe('mailto:emailme@example.com'); expect(urlUtils.prependBaseUrl('javascript:var%20testing=true', 'http://example.com')).toBe('javascript:var%20testing=true'); expect(urlUtils.prependBaseUrl('http://alreadyabsolute.com', 'http://example.com')).toBe('http://alreadyabsolute.com'); + expect(urlUtils.prependBaseUrl('#local-anchor', 'http://example.com')).toBe('#local-anchor'); done(); }); diff --git a/Clipper/joplin-webclipper/content_scripts/index.js b/Clipper/joplin-webclipper/content_scripts/index.js index 67c8af603..3056d935b 100644 --- a/Clipper/joplin-webclipper/content_scripts/index.js +++ b/Clipper/joplin-webclipper/content_scripts/index.js @@ -72,6 +72,20 @@ return output; } + function getAnchorNames(element) { + const anchors = element.getElementsByTagName('a'); + const output = []; + for (let i = 0; i < anchors.length; i++) { + const anchor = anchors[i]; + if (anchor.id) { + output.push(anchor.id); + } else if (anchor.name) { + output.push(anchor.name); + } + } + return output; + } + // Cleans up element by removing all its invisible children (which we don't want to render as Markdown) function cleanUpElement(element, imageSizes) { const childNodes = element.childNodes; @@ -129,7 +143,7 @@ async function prepareCommandResponse(command) { console.info('Got command: ' + command.name); - const clippedContentResponse = (title, html, imageSizes) => { + const clippedContentResponse = (title, html, imageSizes, anchorNames) => { return { name: 'clippedContent', title: title, @@ -139,6 +153,7 @@ parent_id: command.parent_id, tags: command.tags || '', image_sizes: imageSizes, + anchor_names: anchorNames, }; } @@ -155,7 +170,7 @@ response.warning = 'Could not retrieve simplified version of page - full page has been saved instead.'; return response; } - return clippedContentResponse(article.title, article.body, getImageSizes(document)); + return clippedContentResponse(article.title, article.body, getImageSizes(document), getAnchorNames(document)); } else if (command.name === "isProbablyReaderable") { @@ -168,14 +183,14 @@ const cleanDocument = document.body.cloneNode(true); const imageSizes = getImageSizes(document, true); cleanUpElement(cleanDocument, imageSizes); - return clippedContentResponse(pageTitle(), cleanDocument.innerHTML, imageSizes); + return clippedContentResponse(pageTitle(), cleanDocument.innerHTML, imageSizes, getAnchorNames(document)); } else if (command.name === "selectedHtml") { const range = window.getSelection().getRangeAt(0); const container = document.createElement('div'); container.appendChild(range.cloneContents()); - return clippedContentResponse(pageTitle(), container.innerHTML, getImageSizes(document)); + return clippedContentResponse(pageTitle(), container.innerHTML, getImageSizes(document), getAnchorNames(document)); } else if (command.name === 'screenshot') { @@ -299,7 +314,7 @@ } else if (command.name === "pageUrl") { let url = pageLocationOrigin() + location.pathname + location.search; - return clippedContentResponse(pageTitle(), url, getImageSizes(document)); + return clippedContentResponse(pageTitle(), url, getImageSizes(document), getAnchorNames(document)); } else { throw new Error('Unknown command: ' + JSON.stringify(command)); diff --git a/Clipper/joplin-webclipper/popup/src/bridge.js b/Clipper/joplin-webclipper/popup/src/bridge.js index 9cf7efa27..36a1597b5 100644 --- a/Clipper/joplin-webclipper/popup/src/bridge.js +++ b/Clipper/joplin-webclipper/popup/src/bridge.js @@ -34,6 +34,7 @@ class Bridge { parent_id: command.parent_id, tags: command.tags || '', image_sizes: command.image_sizes || {}, + anchor_names: command.anchor_names || [], }; this.dispatch({ type: 'CLIPPED_CONTENT_SET', content: content }); diff --git a/ElectronClient/app/package-lock.json b/ElectronClient/app/package-lock.json index cec43583e..1d6cb73fd 100644 --- a/ElectronClient/app/package-lock.json +++ b/ElectronClient/app/package-lock.json @@ -159,18 +159,18 @@ "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==" }, "acorn-globals": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.0.tgz", - "integrity": "sha512-hMtHj3s5RnuhvHPowpBYvJVj3rAar82JiDQHvGs1zO0l10ocX/xEdBShNHTJaboucJUsScghp74pH3s7EnHHQw==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.2.tgz", + "integrity": "sha512-BbzvZhVtZP+Bs1J1HcwrQe8ycfO0wStkSGxuul3He3GkHOIZ6eTqOkPuw9IP1X3+IkOo4wiJmwkobzXYz4wewQ==", "requires": { "acorn": "^6.0.1", "acorn-walk": "^6.0.1" }, "dependencies": { "acorn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.5.tgz", - "integrity": "sha512-i33Zgp3XWtmZBMNvCr4azvOFeWVw1Rk6p3hfi3LUDvIFraOMywb1kAtrbi+med14m4Xfpqm3zRZMT+c0FNE7kg==" + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", + "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==" } } }, @@ -1640,14 +1640,14 @@ "dev": true }, "cssom": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.4.tgz", - "integrity": "sha512-+7prCSORpXNeR4/fUP3rL+TzqtiFfhMvTd7uEqMdgPvLPt4+uzFUeufx5RHjGTACCargg/DiEt/moMQmvnfkog==" + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.6.tgz", + "integrity": "sha512-DtUeseGk9/GBW0hl0vVPpU22iHL6YB5BUX7ml1hB+GMpo0NX5G4voX3kdWiMSEguFtcW3Vh3djqNF4aIe6ne0A==" }, "cssstyle": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.1.1.tgz", - "integrity": "sha512-364AI1l/M5TYcFH83JnOH/pSqgaNnKmYgKrm0didZMGKWjQB60dymwWy1rKUgL3J1ffdq9xVi2yGLHdSjjSNog==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.2.2.tgz", + "integrity": "sha512-43wY3kl1CVQSvL7wUY1qXkxVGkStjpkDmVjiIKX8R97uhajy8Bybay78uOtqvh7Q5GK75dNPfW0geWjE6qQQow==", "requires": { "cssom": "0.3.x" } @@ -2223,9 +2223,9 @@ "dev": true }, "escodegen": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz", - "integrity": "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", + "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", "requires": { "esprima": "^3.1.3", "estraverse": "^4.2.0", @@ -3752,10 +3752,11 @@ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "joplin-turndown": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/joplin-turndown/-/joplin-turndown-4.0.11.tgz", - "integrity": "sha512-2oiwWX0nKYi1NVcaprSsrXQkYdGoRtPWFmnXdWQnQW44jlgjFV38B4VrgliwX5ZMq7cbx6A9IBwfXcBL2YV2NA==", + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/joplin-turndown/-/joplin-turndown-4.0.12.tgz", + "integrity": "sha512-HlxkcIiNFSMLBvYktoXqLLHFGuwQYlcPclo0Peeatw3cPe6iFqSsEgEGY/0bYM/fubA/zpPULrJcjST99BO9wQ==", "requires": { + "html-entities": "^1.2.1", "jsdom": "^11.9.0" } }, @@ -4613,9 +4614,9 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, "nwsapi": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.0.9.tgz", - "integrity": "sha512-nlWFSCTYQcHk/6A9FFnfhKc14c3aFhfdNBXgo8Qgi9QTBu/qg3Ww+Uiz9wMzXd1T8GFxPc2QIHB6Qtf2XFryFQ==" + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.4.tgz", + "integrity": "sha512-iGfd9Y6SFdTNldEy2L0GUhcarIutFmk+MPWIn9dmj8NMIup03G08uUF2KGbbmv/Ux4RT0VZJoP/sVbWA6d/VIw==" }, "oauth-sign": { "version": "0.8.2", @@ -5601,21 +5602,28 @@ } }, "request-promise-core": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", - "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", + "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", "requires": { - "lodash": "^4.13.1" + "lodash": "^4.17.11" + }, + "dependencies": { + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + } } }, "request-promise-native": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz", - "integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", + "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==", "requires": { - "request-promise-core": "1.1.1", - "stealthy-require": "^1.1.0", - "tough-cookie": ">=2.3.3" + "request-promise-core": "1.1.2", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" } }, "require-directory": { @@ -6045,9 +6053,9 @@ "integrity": "sha1-Kb9hXUqnEhvdiYsi1LP5vE4qoD0=" }, "symbol-tree": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", - "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=" + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, "syswide-cas": { "version": "5.1.0", diff --git a/ElectronClient/app/package.json b/ElectronClient/app/package.json index 5dda3a2cb..93f4e9bc2 100644 --- a/ElectronClient/app/package.json +++ b/ElectronClient/app/package.json @@ -101,7 +101,7 @@ "highlight.js": "^9.15.6", "html-entities": "^1.2.1", "image-type": "^3.0.0", - "joplin-turndown": "^4.0.11", + "joplin-turndown": "^4.0.12", "joplin-turndown-plugin-gfm": "^1.0.8", "jssha": "^2.3.1", "katex": "^0.10.0", diff --git a/ReactNativeClient/lib/HtmlToMd.js b/ReactNativeClient/lib/HtmlToMd.js index 9ccefa539..37c2ba7e7 100644 --- a/ReactNativeClient/lib/HtmlToMd.js +++ b/ReactNativeClient/lib/HtmlToMd.js @@ -7,6 +7,7 @@ class HtmlToMd { const turndownPluginGfm = require('joplin-turndown-plugin-gfm').gfm const turndown = new TurndownService({ headingStyle: 'atx', + anchorNames: options.anchorNames ? options.anchorNames.map(n => n.trim().toLowerCase()) : [], }) turndown.use(turndownPluginGfm) turndown.remove('script'); diff --git a/ReactNativeClient/lib/services/rest/Api.js b/ReactNativeClient/lib/services/rest/Api.js index 4c0ebd6a3..d125be344 100644 --- a/ReactNativeClient/lib/services/rest/Api.js +++ b/ReactNativeClient/lib/services/rest/Api.js @@ -366,7 +366,7 @@ class Api { const imageSizes = requestNote.image_sizes ? requestNote.image_sizes : {}; - let note = await this.requestNoteToNote(requestNote); + let note = await this.requestNoteToNote_(requestNote); const imageUrls = markdownUtils.extractImageUrls(note.body); @@ -416,7 +416,7 @@ class Api { return this.htmlToMdParser_; } - async requestNoteToNote(requestNote) { + async requestNoteToNote_(requestNote) { const output = { title: requestNote.title ? requestNote.title : '', body: requestNote.body ? requestNote.body : '', @@ -430,6 +430,7 @@ class Api { // rendering but it makes sure everything will be parsed. output.body = await this.htmlToMdParser().parse('
' + requestNote.body_html + '
', { baseUrl: requestNote.base_url ? requestNote.base_url : '', + anchorNames: requestNote.anchor_names ? requestNote.anchor_names : [], }); } diff --git a/ReactNativeClient/lib/urlUtils.js b/ReactNativeClient/lib/urlUtils.js index ecb15ed92..c766f9262 100644 --- a/ReactNativeClient/lib/urlUtils.js +++ b/ReactNativeClient/lib/urlUtils.js @@ -25,6 +25,7 @@ urlUtils.prependBaseUrl = function(url, baseUrl) { if (!url) url = ''; if (!baseUrl) return url; + if (url.indexOf('#') === 0) return url; // Don't prepend if it's a local anchor if (urlUtils.urlProtocol(url)) return url; // Don't prepend the base URL if the URL already has a scheme if (url.length >= 2 && url.indexOf('//') === 0) { // If it starts with // it's a protcol-relative URL