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

Clipper: Improved UI and integration with main app

This commit is contained in:
Laurent Cozic 2018-05-20 10:19:59 +01:00
parent c96a416c2c
commit 7ed9c2770c
43 changed files with 4826 additions and 1373 deletions

View File

@ -4,6 +4,24 @@
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"abab": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz",
"integrity": "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4="
},
"acorn": {
"version": "5.5.3",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz",
"integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ=="
},
"acorn-globals": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.1.0.tgz",
"integrity": "sha512-KjZwU26uG3u6eZcfGbTULzFcsoz6pegNKtHPksZPOUsiKo5bUmiBPa38FuHZ/Eun+XYh/JCCkS9AS3Lu4McQOQ==",
"requires": {
"acorn": "^5.0.0"
}
},
"ajv": {
"version": "5.5.2",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
@ -33,6 +51,11 @@
"resolved": "https://registry.npmjs.org/app-module-path/-/app-module-path-2.2.0.tgz",
"integrity": "sha1-ZBqlXft9am8KgUHEucCqULbCTdU="
},
"array-equal": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz",
"integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM="
},
"asap": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
@ -64,6 +87,11 @@
}
}
},
"async-limiter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
},
"async-mutex": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.1.3.tgz",
@ -122,6 +150,11 @@
"concat-map": "0.0.1"
}
},
"browser-process-hrtime": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.2.tgz",
"integrity": "sha1-Ql1opY00R/AqBKqJQYf86K+Le44="
},
"camel-case": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
@ -277,6 +310,19 @@
}
}
},
"cssom": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.2.tgz",
"integrity": "sha1-uANhcMefB6kP8vFuIihAJ6JDhIs="
},
"cssstyle": {
"version": "0.2.37",
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.37.tgz",
"integrity": "sha1-VBCXI0yyUTyDzu06zdwn/yeYfVQ=",
"requires": {
"cssom": "0.3.x"
}
},
"cwise-compiler": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/cwise-compiler/-/cwise-compiler-1.1.3.tgz",
@ -298,6 +344,16 @@
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-0.0.3.tgz",
"integrity": "sha1-GK6XmmoMqZSwYlhTkW0mYruuCxo="
},
"data-urls": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.0.0.tgz",
"integrity": "sha512-ai40PPQR0Fn1lD2PPie79CibnlMN2AYiDhwFX/rZHVsxbs5kNJSjegqXIprhouGXlRdEnfybva7kqRGnB6mypA==",
"requires": {
"abab": "^1.0.4",
"whatwg-mimetype": "^2.0.0",
"whatwg-url": "^6.4.0"
}
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@ -329,6 +385,14 @@
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-0.2.0.tgz",
"integrity": "sha1-R/31ZzSKF+wl/L8LnkRjSKdvn7U="
},
"domexception": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz",
"integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==",
"requires": {
"webidl-conversions": "^4.0.2"
}
},
"ecc-jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
@ -398,6 +462,41 @@
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
},
"escodegen": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.1.tgz",
"integrity": "sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q==",
"requires": {
"esprima": "^3.1.3",
"estraverse": "^4.2.0",
"esutils": "^2.0.2",
"optionator": "^0.8.1",
"source-map": "~0.6.1"
},
"dependencies": {
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"optional": true
}
}
},
"esprima": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
"integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM="
},
"estraverse": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
"integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM="
},
"esutils": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
},
"exit": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
@ -424,6 +523,11 @@
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
},
"fast-levenshtein": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
},
"fault": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/fault/-/fault-1.0.2.tgz",
@ -610,6 +714,14 @@
"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz",
"integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA=="
},
"html-encoding-sniffer": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz",
"integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==",
"requires": {
"whatwg-encoding": "^1.0.1"
}
},
"html-entities": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz",
@ -789,6 +901,39 @@
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
"optional": true
},
"jsdom": {
"version": "11.10.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.10.0.tgz",
"integrity": "sha512-x5No5FpJgBg3j5aBwA8ka6eGuS5IxbC8FOkmyccKvObtFT0bDMict/LOxINZsZGZSfGdNomLZ/qRV9Bpq/GIBA==",
"requires": {
"abab": "^1.0.4",
"acorn": "^5.3.0",
"acorn-globals": "^4.1.0",
"array-equal": "^1.0.0",
"cssom": ">= 0.3.2 < 0.4.0",
"cssstyle": ">= 0.2.37 < 0.3.0",
"data-urls": "^1.0.0",
"domexception": "^1.0.0",
"escodegen": "^1.9.0",
"html-encoding-sniffer": "^1.0.2",
"left-pad": "^1.2.0",
"nwmatcher": "^1.4.3",
"parse5": "4.0.0",
"pn": "^1.1.0",
"request": "^2.83.0",
"request-promise-native": "^1.0.5",
"sax": "^1.2.4",
"symbol-tree": "^3.2.2",
"tough-cookie": "^2.3.3",
"w3c-hr-time": "^1.0.1",
"webidl-conversions": "^4.0.2",
"whatwg-encoding": "^1.0.3",
"whatwg-mimetype": "^2.1.0",
"whatwg-url": "^6.4.0",
"ws": "^4.0.0",
"xml-name-validator": "^3.0.0"
}
},
"json-schema": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
@ -828,11 +973,25 @@
"resolved": "https://registry.npmjs.org/jssha/-/jssha-2.3.1.tgz",
"integrity": "sha1-FHshJTaQNcpLL30hDcU58Amz3po="
},
"left-pad": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz",
"integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA=="
},
"levenshtein": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/levenshtein/-/levenshtein-1.0.5.tgz",
"integrity": "sha1-ORFzepy1baNF0Aj1V4LG8TiXm6M="
},
"levn": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
"integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
"requires": {
"prelude-ls": "~1.1.2",
"type-check": "~0.3.2"
}
},
"lodash": {
"version": "4.17.4",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
@ -843,6 +1002,11 @@
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.4.tgz",
"integrity": "sha1-3MHXVS4VCgZABzupyzHXDwMpUOc="
},
"lodash.sortby": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
"integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg="
},
"lodash.toarray": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz",
@ -1028,6 +1192,11 @@
"pify": "^3.0.0"
}
},
"nwmatcher": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.4.tgz",
"integrity": "sha512-3iuY4N5dhgMpCUrOVnuAdGrgxVqV2cJpM+XNccjR2DKOB1RUP0aA+wGXEiNziG/UKboFyGBIoKOaNlJxx8bciQ=="
},
"oauth-sign": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
@ -1051,6 +1220,26 @@
"wrappy": "1"
}
},
"optionator": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
"integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
"requires": {
"deep-is": "~0.1.3",
"fast-levenshtein": "~2.0.4",
"levn": "~0.3.0",
"prelude-ls": "~1.1.2",
"type-check": "~0.3.2",
"wordwrap": "~1.0.0"
},
"dependencies": {
"deep-is": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ="
}
}
},
"param-case": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
@ -1067,6 +1256,11 @@
"data-uri-to-buffer": "0.0.3"
}
},
"parse5": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
"integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA=="
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
@ -1083,11 +1277,21 @@
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
},
"pn": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz",
"integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA=="
},
"pngjs": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-2.3.1.tgz",
"integrity": "sha1-EdHhK5y2TWPjDBQ6Mw9MH1Z9qF8="
},
"prelude-ls": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
"integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ="
},
"process-nextick-args": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
@ -1203,6 +1407,24 @@
"uuid": "^3.1.0"
}
},
"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=",
"requires": {
"lodash": "^4.13.1"
}
},
"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=",
"requires": {
"request-promise-core": "1.1.1",
"stealthy-require": "^1.1.0",
"tough-cookie": ">=2.3.3"
}
},
"requires-port": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
@ -2037,6 +2259,11 @@
"tweetnacl": "~0.14.0"
}
},
"stealthy-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
"integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks="
},
"strict-uri-encode": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
@ -2107,6 +2334,11 @@
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz",
"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="
},
"tar": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/tar/-/tar-4.4.0.tgz",
@ -2191,6 +2423,21 @@
"punycode": "^1.4.1"
}
},
"tr46": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
"integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=",
"requires": {
"punycode": "^2.1.0"
},
"dependencies": {
"punycode": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz",
"integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0="
}
}
},
"tree-kit": {
"version": "0.5.26",
"resolved": "https://registry.npmjs.org/tree-kit/-/tree-kit-0.5.26.tgz",
@ -2204,12 +2451,33 @@
"safe-buffer": "^5.0.1"
}
},
"turndown": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/turndown/-/turndown-4.0.2.tgz",
"integrity": "sha512-pqZ6WrHFGnxXC9q2xJ3Qa7EoLAwrojgFRajWZjxTKwbz9vnNnyi8lLjiD5h86UTPOcMlEyHjm6NMhjEDdlc25A==",
"requires": {
"jsdom": "^11.9.0"
}
},
"turndown-plugin-gfm": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/turndown-plugin-gfm/-/turndown-plugin-gfm-1.0.2.tgz",
"integrity": "sha512-vwz9tfvF7XN/jE0dGoBei3FXWuvll78ohzCZQuOb+ZjWrs3a0XhQVomJEb2Qh4VHTPNRO4GPZh0V7VRbiWwkRg=="
},
"tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
"optional": true
},
"type-check": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
"integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
"requires": {
"prelude-ls": "~1.1.2"
}
},
"uglify-js": {
"version": "3.3.25",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.25.tgz",
@ -2285,11 +2553,52 @@
"extsprintf": "^1.2.0"
}
},
"w3c-hr-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz",
"integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=",
"requires": {
"browser-process-hrtime": "^0.1.2"
}
},
"webidl-conversions": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
"integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="
},
"whatwg-encoding": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.3.tgz",
"integrity": "sha512-jLBwwKUhi8WtBfsMQlL4bUUcT8sMkAtQinscJAe/M4KHCkHuUJAF6vuB0tueNIw4c8ziO6AkRmgY+jL3a0iiPw==",
"requires": {
"iconv-lite": "0.4.19"
}
},
"whatwg-mimetype": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.1.0.tgz",
"integrity": "sha512-FKxhYLytBQiUKjkYteN71fAUA3g6KpNXoho1isLiLSB3N1G4F35Q5vUxWfKFhBwi5IWF27VE6WxhrnnC+m0Mew=="
},
"whatwg-url": {
"version": "6.4.1",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.4.1.tgz",
"integrity": "sha512-FwygsxsXx27x6XXuExA/ox3Ktwcbf+OAvrKmLulotDAiO1Q6ixchPFaHYsis2zZBZSJTR0+dR+JVtf7MlbqZjw==",
"requires": {
"lodash.sortby": "^4.7.0",
"tr46": "^1.0.1",
"webidl-conversions": "^4.0.2"
}
},
"word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ=="
},
"wordwrap": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
"integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus="
},
"wrap-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz",
@ -2304,6 +2613,20 @@
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"ws": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-4.1.0.tgz",
"integrity": "sha512-ZGh/8kF9rrRNffkLFV4AzhvooEclrOH0xaugmqGsIfFgOE/pIz4fMc4Ef+5HSQqTEug2S9JZIWDR47duDSLfaA==",
"requires": {
"async-limiter": "~1.0.0",
"safe-buffer": "~5.1.0"
}
},
"xml-name-validator": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",
"integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw=="
},
"xml2js": {
"version": "0.4.19",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",

View File

@ -60,6 +60,8 @@
"tar": "^4.4.0",
"tcp-port-used": "^0.1.2",
"tkwidgets": "^0.5.26",
"turndown": "^4.0.2",
"turndown-plugin-gfm": "^1.0.2",
"url-parse": "^1.2.0",
"uuid": "^3.0.1",
"valid-url": "^1.0.9",

View File

@ -20,4 +20,4 @@ fi
(cd "$ROOT_DIR" && npm test tests-build/models_Note.js)
(cd "$ROOT_DIR" && npm test tests-build/models_Folder.js)
(cd "$ROOT_DIR" && npm test tests-build/services_InteropService.js)
(cd "$ROOT_DIR" && npm test tests-build/HtmlToMd.js)
(cd "$ROOT_DIR" && npm test tests-build/EnexToMd.js)

View File

@ -0,0 +1,62 @@
require('app-module-path').addPath(__dirname);
const { time } = require('lib/time-utils.js');
const { filename } = require('lib/path-utils.js');
const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
const Folder = require('lib/models/Folder.js');
const Note = require('lib/models/Note.js');
const BaseModel = require('lib/BaseModel.js');
const { shim } = require('lib/shim');
const { enexXmlToMd } = require('lib/import-enex-md-gen.js');
jasmine.DEFAULT_TIMEOUT_INTERVAL = 60 * 60 * 1000; // Can run for a while since everything is in the same test unit
process.on('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
});
describe('EnexToMd', function() {
beforeEach(async (done) => {
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
done();
});
it('should convert from Enex to Markdown', asyncTest(async () => {
const basePath = __dirname + '/enex_to_md';
const files = await shim.fsDriver().readDirStats(basePath);
for (let i = 0; i < files.length; i++) {
const htmlFilename = files[i].path;
if (htmlFilename.indexOf('.html') < 0) continue;
const htmlPath = basePath + '/' + htmlFilename;
const mdPath = basePath + '/' + filename(htmlFilename) + '.md';
// if (htmlFilename !== 'text2.html') continue;
const html = await shim.fsDriver().readFile(htmlPath);
const expectedMd = await shim.fsDriver().readFile(mdPath);
const actualMd = await enexXmlToMd('<div>' + html + '</div>', []);
if (actualMd !== expectedMd) {
console.info('');
console.info('Error converting file: ' + htmlFilename);
console.info('--------------------------------- Got:');
console.info(actualMd.split('\n'));
console.info('--------------------------------- Expected:');
console.info(expectedMd.split('\n'));
console.info('--------------------------------------------');
console.info('');
expect(false).toBe(true);
// return;
} else {
expect(true).toBe(true)
}
}
}));
});

View File

@ -7,6 +7,7 @@ const Folder = require('lib/models/Folder.js');
const Note = require('lib/models/Note.js');
const BaseModel = require('lib/BaseModel.js');
const { shim } = require('lib/shim');
const HtmlToMd = require('lib/HtmlToMd');
const { enexXmlToMd } = require('lib/import-enex-md-gen.js');
jasmine.DEFAULT_TIMEOUT_INTERVAL = 60 * 60 * 1000; // Can run for a while since everything is in the same test unit
@ -23,9 +24,10 @@ describe('HtmlToMd', function() {
done();
});
it('should convert from HTML to Markdown', asyncTest(async () => {
it('should convert from Enex to Markdown', asyncTest(async () => {
const basePath = __dirname + '/html_to_md';
const files = await shim.fsDriver().readDirStats(basePath);
const htmlToMd = new HtmlToMd();
for (let i = 0; i < files.length; i++) {
const htmlFilename = files[i].path;
@ -34,12 +36,12 @@ describe('HtmlToMd', function() {
const htmlPath = basePath + '/' + htmlFilename;
const mdPath = basePath + '/' + filename(htmlFilename) + '.md';
// if (htmlFilename !== 'text2.html') continue;
if (htmlFilename !== 'table_no_header.html') continue;
const html = await shim.fsDriver().readFile(htmlPath);
const expectedMd = await shim.fsDriver().readFile(mdPath);
const actualMd = await enexXmlToMd('<div>' + html + '</div>', []);
const actualMd = await htmlToMd.parse('<div>' + html + '</div>', []);
if (actualMd !== expectedMd) {
console.info('');

View File

@ -0,0 +1 @@
<script id="appnexus-adload" data-reactid="7">window.apntag=window.apntag||{};window.apntag.anq=window.apntag.anq||[];</script>

View File

@ -0,0 +1,4 @@
<table>
<tr><td>No</td><td>header</td></tr>
<tr><td>And no</td><td>suprises</td></tr>
</table>

View File

@ -0,0 +1,4 @@
| | |
| --- | --- |
| No | header |
| And no | suprises |

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -27,7 +27,10 @@
for (let i = 0; i < childNodes.length; i++) {
const node = childNodes[i];
const isVisible = node.nodeType === 1 ? window.getComputedStyle(node).display !== 'none' : true;
let isVisible = node.nodeType === 1 ? window.getComputedStyle(node).display !== 'none' : true;
if (isVisible && ['input', 'textarea', 'script', 'style', 'select', 'option', 'button'].indexOf(node.nodeName.toLowerCase()) >= 0) isVisible = false;
if (!isVisible) {
element.removeChild(node);
} else {
@ -48,7 +51,7 @@
// Readability directly change the passed document so clone it so as
// to preserve the original web page.
const documentClone = document.cloneNode(true);
const readability = new window.Readability(uri, documentClone);
const readability = new Readability(documentClone); // new window.Readability(uri, documentClone);
const article = readability.parse();
if (!article) throw new Error('Could not parse HTML document with Readability');
@ -95,13 +98,6 @@
url: location.origin + location.pathname,
};
} else if (command.name === "pageTitle") {
return {
name: 'pageTitle',
text: pageTitle(),
};
} else {
throw new Error('Unknown command', command);
}

View File

@ -1,5 +1,93 @@
.App {
text-align: center;
width: 400px;
height: 400px;
width: 400px;
height: 600px;
overflow-x: hidden;
overflow-y: hidden;
display: flex;
flex-direction: column;
background-color: #162b3d;
font-size: 1em;
}
.App h2 {
font-size: 1em;
color: #5A95C7;
padding-left: 10px;
margin-top: .5em;
margin-bottom: .5em;
font-weight: normal;
}
.App .Disabled {
opacity: .5;
}
.App .Controls {
flex: 0;
padding-top: 10px;
}
.App .Controls ul {
flex: 0;
list-style-type: none;
padding: 0 10px;
margin: 0;
display: flex;
flex-direction: column;
align-items: stretch;
}
.App a.Button {
background-color: #0269c2;
padding: 8px 14px;
display: flex;
flex: 1;
color: #eee;
font-weight: normal;
font-size: .8em;
cursor: pointer;
}
.App a.Button:hover {
background-color: #1E89E6;
}
.App .Controls a.Button {
margin-bottom: 10px;
}
.App .Preview {
min-height: 0;
flex: 1;
align-items: stretch;
margin: 0 10px 10px 10px;
display: flex;
flex-direction: column;
/*border: 2px solid red;*/
}
.App .Preview .Info {
color: #38668D;
}
.App .Preview .Title {
flex: 0;
margin-bottom: 10px;
}
.App .Preview .Body {
flex: 1;
font-size: .5em;
overflow-x: hidden;
overflow-y: scroll;
overflow-wrap: break-word;
background-color: #ffffff;
flex-shrink: 1;
min-width: auto;
padding: 10px;
margin-bottom: 10px;
}
.App .Preview .Confirm {
flex: 0;
}

View File

@ -13,6 +13,17 @@ class AppComponent extends Component {
this.state = ({
contentScriptLoaded: false,
});
this.confirm_click = () => {
bridge().sendContentToJoplin(this.props.clippedContent);
}
this.contentTitle_change = (event) => {
this.props.dispatch({
type: 'CLIPPED_CONTENT_TITLE_SET',
text: event.currentTarget.value
});
}
}
async clipSimplified_click() {
@ -28,7 +39,8 @@ class AppComponent extends Component {
}
async loadContentScripts() {
await Global.browser().tabs.executeScript({file: "/content_scripts/vendor.bundle.js"});
await Global.browser().tabs.executeScript({file: "/content_scripts/JSDOMParser.js"});
await Global.browser().tabs.executeScript({file: "/content_scripts/Readability.js"});
await Global.browser().tabs.executeScript({file: "/content_scripts/index.js"});
}
@ -37,25 +49,65 @@ class AppComponent extends Component {
this.setState({
contentScriptLoaded: true,
});
bridge().sendCommandToActiveTab({
name: 'pageTitle',
});
}
render() {
if (!this.state.contentScriptLoaded) return 'Loading...';
const warningComponent = !this.props.warning ? null : <div>{ this.props.warning }</div>
const warningComponent = !this.props.warning ? null : <div className="Warning">{ this.props.warning }</div>
const hasContent = !!this.props.clippedContent;
const content = this.props.clippedContent;
let previewComponent = null;
const operation = this.props.contentUploadOperation;
if (operation) {
let msg = '';
if (operation.uploading) {
msg = 'Sending to Joplin...';
} else if (operation.success) {
msg = 'Note was successfully created!';
} else {
msg = 'There was some error creating the note: ' + operation.errorMessage;
}
previewComponent = (
<div className="Preview">
<p className="Info">{ msg }</p>
</div>
);
} else {
if (hasContent) {
previewComponent = (
<div className="Preview">
<input className={"Title"} value={content.title} onChange={this.contentTitle_change}/>
<div className={"Body"} dangerouslySetInnerHTML={{__html: content.bodyHtml}}></div>
<a className={"Confirm Button"} onClick={this.confirm_click}>Confirm</a>
</div>
);
} else {
previewComponent = (
<div className="Preview">
<p className="Info">(No preview yet)</p>
</div>
);
}
}
return (
<div className="App">
<p>Title: { this.props.pageTitle }</p>
<ul>
<li><button onClick={this.clipSimplified_click}>Clip simplified page</button></li>
<li><button onClick={this.clipComplete_click}>Clip complete page</button></li>
</ul>
<div className="Controls">
<ul>
<li><a className="Button" onClick={this.clipSimplified_click}>Clip simplified page</a></li>
<li><a className="Button" onClick={this.clipComplete_click}>Clip complete page</a></li>
</ul>
</div>
{ warningComponent }
<h2>Preview:</h2>
{ previewComponent }
</div>
);
}
@ -65,7 +117,8 @@ class AppComponent extends Component {
const mapStateToProps = (state) => {
return {
warning: state.warning,
pageTitle: state.pageTitle,
clippedContent: state.clippedContent,
contentUploadOperation: state.contentUploadOperation,
};
};

View File

@ -17,35 +17,14 @@ class Bridge {
}
if (command.name === 'clippedContent') {
console.info('Popup: Sending to Joplin...');
try {
const response = await fetch("http://127.0.0.1:9967/notes", {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
//make sure to serialize your JSON body
body: JSON.stringify({
title: command.title,
baseUrl: command.baseUrl,
bodyHtml: command.html,
url: command.url,
})
})
console.info('GOT RESPNSE', response);
const json = await response.json();
console.info(json);
} catch (error) {
console.error('Popup: Cannot send to Joplin', error)
}
} else if (command.name === 'pageTitle') {
this.dispatch({ type: 'PAGE_TITLE_SET', text: command.text });
const content = {
title: command.title,
bodyHtml: command.html,
baseUrl: command.baseUrl,
url: command.url,
};
this.dispatch({ type: 'CLIPPED_CONTENT_SET', content: content });
}
}
@ -67,9 +46,38 @@ class Bridge {
return;
}
this.dispatch({ type: 'CONTENT_UPLOAD', operation: null });
await this.browser().tabs.sendMessage(tabs[0].id, command);
}
async sendContentToJoplin(content) {
console.info('Popup: Sending to Joplin...');
try {
this.dispatch({ type: 'CONTENT_UPLOAD', operation: { uploading: true } });
if (!content) throw new Error('Cannot send empty content');
const response = await fetch("http://127.0.0.1:9967/notes", {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(content)
})
if (!response.ok) {
this.dispatch({ type: 'CONTENT_UPLOAD', operation: { uploading: false, success: false, errorMessage: response.text() } });
} else {
this.dispatch({ type: 'CONTENT_UPLOAD', operation: { uploading: false, success: true } });
}
} catch (error) {
this.dispatch({ type: 'CONTENT_UPLOAD', operation: { uploading: false, success: false, errorMessage: error.message } });
}
}
}
const bridge_ = new Bridge();

View File

@ -9,7 +9,8 @@ const { createStore } = require('redux');
const defaultState = {
warning: '',
pageTitle: '',
clippedContent: null,
contentUploadOperation: null,
};
function reducer(state = defaultState, action) {
@ -20,10 +21,22 @@ function reducer(state = defaultState, action) {
newState = Object.assign({}, state);
newState.warning = action.text;
} else if (action.type === 'PAGE_TITLE_SET') {
} else if (action.type === 'CLIPPED_CONTENT_SET') {
newState = Object.assign({}, state);
newState.pageTitle = action.text;
newState.clippedContent = action.content;
} else if (action.type === 'CLIPPED_CONTENT_TITLE_SET') {
newState = Object.assign({}, state);
const newContent = newState.clippedContent ? Object.assign({}, newState.clippedContent) : {};
newContent.title = action.text;
newState.clippedContent = newContent;
} else if (action.type === 'CONTENT_UPLOAD') {
newState = Object.assign({}, state);
newState.contentUploadOperation = action.operation;
}

File diff suppressed because it is too large Load Diff

View File

@ -116,6 +116,8 @@
"string-to-stream": "^1.1.0",
"tar": "^4.4.0",
"tcp-port-used": "^0.1.2",
"turndown": "^4.0.2",
"turndown-plugin-gfm": "^1.0.2",
"url-parse": "^1.2.0",
"uuid": "^3.1.0",
"valid-url": "^1.0.9",

View File

@ -3,8 +3,11 @@ const TurndownService = require('turndown')
class HtmlToMd {
parse(html) {
const turndownService = new TurndownService()
let markdown = turndownService.turndown(html)
const turndownPluginGfm = require('turndown-plugin-gfm').gfm
const turndown = new TurndownService()
turndown.use(turndownPluginGfm)
turndown.remove('script');
let markdown = turndown.turndown(html)
return markdown;
}