From d9fc8f5f0fdccc94c4073cfba6861fd7a0d0ddf6 Mon Sep 17 00:00:00 2001 From: almenon Date: Sun, 22 Dec 2019 15:10:25 -0800 Subject: [PATCH 01/16] #1 update library to turndown --- lib/convertFromUrl.js | 11 +- lib/mdConverters.js | 30 -- package-lock.json | 849 ++++++++++++++++++++++++++++++++++++++++++ package.json | 10 +- 4 files changed, 860 insertions(+), 40 deletions(-) delete mode 100644 lib/mdConverters.js create mode 100644 package-lock.json diff --git a/lib/convertFromUrl.js b/lib/convertFromUrl.js index e2794de..ba62afa 100644 --- a/lib/convertFromUrl.js +++ b/lib/convertFromUrl.js @@ -1,11 +1,12 @@ 'use strict'; -const Promise = require('bluebird'); const request = require('request'); const cheerio = require('cheerio'); -const toMarkdown = require('to-markdown'); +const TurndownService = require('turndown') +const gfm = require('turndown-plugin-gfm').gfm -const converters = require('./mdConverters'); +const turndownService = new TurndownService() +turndownService.use(gfm) function convertFromUrl(url) { return new Promise(function(resolve, reject) { @@ -16,10 +17,10 @@ function convertFromUrl(url) { if (err) return reject(err); - + let $ = cheerio.load(body); let html = $('article').html() || ''; - let markdown = toMarkdown(html, { gfm: true, converters: converters }); + let markdown = turndownService.turndown(html); resolve(markdown); diff --git a/lib/mdConverters.js b/lib/mdConverters.js deleted file mode 100644 index d6a2aeb..0000000 --- a/lib/mdConverters.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; - -const converters = [ - { - filter: 'section', - replacement: function(content) { - return content; - } - }, - { - filter: 'div', - replacement: function(content) { - return content; - } - }, - { - filter: 'figure', - replacement: function(content) { - return content; - } - }, - { - filter: 'figcaption', - replacement: function(content) { - return content; - } - } -]; - -module.exports = converters diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..64ec2d4 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,849 @@ +{ + "name": "medium-to-markdown", + "version": "0.0.2", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/node": { + "version": "12.12.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.21.tgz", + "integrity": "sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA==" + }, + "acorn-walk": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==" + }, + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=" + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.0.tgz", + "integrity": "sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A==" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + }, + "browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "cheerio": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz", + "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==", + "requires": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.1", + "entities": "~1.1.1", + "htmlparser2": "^3.9.1", + "lodash": "^4.15.0", + "parse5": "^3.0.1" + }, + "dependencies": { + "parse5": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", + "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", + "requires": { + "@types/node": "*" + } + } + } + }, + "combined-stream": { + "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" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "requires": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "css-what": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" + }, + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "abab": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz", + "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==" + }, + "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" + } + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "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=" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "dom-serializer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "requires": { + "domelementtype": "^1.3.0", + "entities": "^1.1.1" + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "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" + } + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + }, + "escodegen": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.12.0.tgz", + "integrity": "sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg==", + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "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" + } + }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "left-pad": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==" + }, + "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.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" + }, + "mime-db": { + "version": "1.42.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz", + "integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==" + }, + "mime-types": { + "version": "2.1.25", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz", + "integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==", + "requires": { + "mime-db": "1.42.0" + } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "requires": { + "boolbase": "~1.0.0" + } + }, + "nwsapi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==" + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "psl": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.6.0.tgz", + "integrity": "sha512-SYKKmVel98NCOYXpkwUqZqh0ahZeeKfmisiLIcEZdsb+WbLv02g/dI5BUmZnIyOe7RzZtLax81nnb2HbvC2tzA==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "readable-stream": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", + "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "request-promise-core": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz", + "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==", + "requires": { + "lodash": "^4.17.15" + } + }, + "request-promise-native": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz", + "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==", + "requires": { + "request-promise-core": "1.1.3", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "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 + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "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=" + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "symbol-tree": { + "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==" + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "turndown": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/turndown/-/turndown-5.0.3.tgz", + "integrity": "sha512-popfGXEiedpq6F5saRIAThKxq/bbEPVFnsDnUdjaDGIre9f3/OL9Yi/yPbPcZ7RYUDpekghr666bBfZPrwNnhQ==", + "requires": { + "jsdom": "^11.9.0" + }, + "dependencies": { + "abab": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz", + "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==" + }, + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==" + }, + "acorn-globals": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", + "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", + "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==" + } + } + }, + "cssstyle": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", + "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", + "requires": { + "cssom": "0.3.x" + } + }, + "jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "requires": { + "abab": "^2.0.0", + "acorn": "^5.5.3", + "acorn-globals": "^4.1.0", + "array-equal": "^1.0.0", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": "^1.0.0", + "data-urls": "^1.0.0", + "domexception": "^1.0.1", + "escodegen": "^1.9.1", + "html-encoding-sniffer": "^1.0.2", + "left-pad": "^1.3.0", + "nwsapi": "^2.0.7", + "parse5": "4.0.0", + "pn": "^1.1.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.5", + "sax": "^1.2.4", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.3.4", + "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.1", + "ws": "^5.2.0", + "xml-name-validator": "^3.0.0" + } + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==" + }, + "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" + } + }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "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==" + } + } + }, + "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=" + }, + "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" + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "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.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" + }, + "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==" + }, + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "requires": { + "async-limiter": "~1.0.0" + } + } + } +} diff --git a/package.json b/package.json index f7c6abb..174a5ad 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "import a medium URL and convert it to markdown", "main": "index.js", "scripts": { - "start": "node index.js", + "convert": "node index.js", "test": "echo \"Error: no test specified\" && exit 1" }, "author": "SkillFlow, Inc.", @@ -16,10 +16,10 @@ "markdown" ], "dependencies": { - "bluebird": "^3.5.0", - "cheerio": "^0.22.0", - "request": "^2.81.0", - "to-markdown": "^3.0.4" + "cheerio": "^1.0.0-rc.3", + "request": "^2.88.0", + "turndown": "^5.0.3", + "turndown-plugin-gfm": "^1.0.2" }, "repository": { "type": "git", From 3237ccb1ef59fb7cb2c9aedfd352e3f0a65c25d9 Mon Sep 17 00:00:00 2001 From: almenon Date: Sun, 22 Dec 2019 15:11:03 -0800 Subject: [PATCH 02/16] add example output --- exampleOutput.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 exampleOutput.md diff --git a/exampleOutput.md b/exampleOutput.md new file mode 100644 index 0000000..27b10b4 --- /dev/null +++ b/exampleOutput.md @@ -0,0 +1,39 @@ + +> medium-to-markdown@0.0.2 convert C:\dev\misc\medium-to-markdown +> node index.js "https://medium.com/@almenon214/keeping-yourself-motivated-as-a-coder-a16a6fcf49c7" + +Keeping yourself motivated as a coder +===================================== + +[![Almenon](https://miro.medium.com/fit/c/96/96/1*4FAOBq9qVna6uHkxaolTtA.png)](/@almenon214?source=post_page-----a16a6fcf49c7----------------------) + +[Almenon](/@almenon214?source=post_page-----a16a6fcf49c7----------------------) + +Follow + +[Sep 23, 2018](/@almenon214/keeping-yourself-motivated-as-a-coder-a16a6fcf49c7?source=post_page-----a16a6fcf49c7----------------------) · 4 min read + +Programmers probably have one of the most distracting jobs in existence. Their entire workday is spent in front of a computer — a literally endless source of entertainment and pleasure, a limitless virtual heaven. With literally just a click of a button, you could be in another world. You could be slaying dragons. You could be learning about the [great molasses flood of 1919](https://www.damninteresting.com/the-great-molasses-flood-of-1919/). You could literally be doing _anything._ So why do programmers spend their time programming, a hobby that could only be described as exciting by masochistic workaholics? + +![](https://miro.medium.com/max/60/1*S15R5ty8G-kRGo-ghk2EGA.jpeg?q=20) + + + +Pictured: sticky, sweet, syrupy disaster + +Well, the vast sums of money that a software engineer gets is a pretty good reason. Another reason is that they probably are workaholics. You don’t see doctors spending all-nighters at hackathons for a 20$ starbucks giftcard, or linguists designing [languages composed of Arnold Schwarzenegger quotes](http://lhartikk.github.io/ArnoldC/) as a joke. + +Or maybe they do it for the pride. Making open source projects gets you virtual street cred — the bigger the project, the better the cred. Guido, the creator of python, is practically a king. Before abdicating his throne he was called the BDFL, or _benevolent dictator for life_. Contributing to a project is a way of becoming something greater than youself and leaving a lasting mark on society. Make a commit, and git will forever stamp you into history, a hash 785b312 saying **_I was there_**_._ _xNinja47, 4/30/2005, changed 3 files for the better_. + +Or it could just be for practical reasons — you need to keep your skills sharp, after all. And open source work looks good on your resume. Not everyone loves programming — for some it’s just a high paying job to slog through untill they get home to their families and social life. + +But if you’re reading this article, maybe you _don’t_ have anything to motivate you. Maybe reddit sounds like a good idea. Stop! Don’t do it! No [funny cat pics](https://i.reddituploads.com/788c8a3ab05243d59259410aa0eb71f9?fit=max&h=1536&w=1536&s=47f691afce2df783c20f31d702427957)! No [cute bears](https://i.redd.it/vkyg59t2ddp01.jpg)! Keep on writing this medium article! (_I may be speaking to myself here)_. So without further ado, here is some strategies to employ for keeping yourself in shape: + +1. **Deadlines**: set deadlines for yourself — github [milestones](https://github.com/Almenon/AREPL-vscode/milestones?state=closed) and [issues](https://github.com/Almenon/AREPL-vscode/issues) are great for this. If you look at my projects I have _hundreds_ of issues I create for myself to keep track of my work. Another benefit of writing issues is that you have written documentation to refer to when you go back to working on it. Or if you’re not on github, you can simply set up calendar events. Maybe even tell your friends that you will get something done by a certain time — that creates commitment. +2. **Releases.** Your project is a piece of crap. It barely functions, the architecture is horrible, and [you don’t even really know what you’re doing](https://en.wikipedia.org/wiki/Impostor_syndrome). The last thing you want to do is to expose your baby duckling to the public. But at a certain point you have to cut your losses — you can’t just keep on working on something forever, because then you’re going to have burnout. And you may be pleasantly surprised. Maybe people will like it. Worst case scenario, people will hate it, but in the process of shitting all over it they inadvertently give you helpful advice to fix it. In fact, in my experience the detractors are more helpful than the fans, because they will give you actual advice, not just “oh that looks cool”. +3. **Maximize Fun**. Look for more pleasurable and fulfilling fun, rather than lazy and cheap entertainment. For example, it’s far too easy to _control-n_ to open a new tab and type in the letter r to get the autocomplete for reddit. That’s just 3 keys and a enter. Reddit is fun, I love it, but its filled with low effort reposts. Taking the time to watch a show or even a movie might be a better idea — you have a clear chance to stop (at the end) rather than scrolling through reddit’s infinite amount of content. Important disclaimer: _never_ click on netflix’s next episode button. That’s a feature designed by the devil to get you to binge-watch shows and hate yourself afterwards. If you actually have time to watch the next episode then you can wait for the credits to go by. Or more likely, realize what you are doing and go do something productive. +4. **Take walks.** Rest your eyes. Think about how to approach the problem. If you’re me, try reading while walking. It’s not that dangerous — you’ve only bumped into a pole once or twice. +5. **Get the support of others**. Join a slack/discord community. Make a program that other people use. Ask for advice from your friends. Go to programming meetups. Go to [programming conventions](/@almenon214/pycon-2018-6b1c45889e3b) — it’s a great excuse for a vacation, and it’s a lot less dry than it sounds. Go past your normal boundaries — you might be surprised as to what you are capable of. +6. **Add** [**telemetry**](/@almenon214/adding-telemetry-to-your-vscode-extension-f3d52d2e573c) **or** [**alerting**](/@almenon214/setting-up-email-alerts-for-your-vscode-extension-using-azure-d755651b2e0d) **to your program**. It might not be practical for a small application, but it is _extremely_ useful as a motivating tool. Every day I get emails from around the world. People use [AREPL](https://github.com/Almenon/AREPL-vscode) in [New York, Canada, Brazil, Chile. Europe, Japan, Israel, and Pakistan](/@almenon214/arepl-stats-for-june-5e0c87636c3). Every day it’s a different country. It’s significant to know that people are using what I make and relying on me to continue developing it. In a similar vein, I also get emails whenever my reddit bot posts. I can see if people upvote it or if there are problems with the bot I need to fix. + +Hopefully these tips are helpful to you. If they are, I’d love to hear it. Or maybe you have a tip of your own — either way, leave a comment below! From 0ca1fe8606018ab332e96683ee96ea69fc8a84c9 Mon Sep 17 00:00:00 2001 From: almenon Date: Sun, 22 Dec 2019 15:11:27 -0800 Subject: [PATCH 03/16] add ability to run from command line --- index.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 58f443c..85a894a 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,18 @@ 'use strict'; +const convertFromUrl = require('./lib/convertFromUrl') + module.exports = { - convertFromUrl: require('./lib/convertFromUrl') + convertFromUrl +} + +// if run as cmd utility +if (typeof require !== 'undefined' && require.main === module) { + if(process.argv.length < 3){ + console.log('What url to convert?') + return + } + convertFromUrl(process.argv[2]).then(function (markdown) { + console.log(markdown); //=> Markdown content of medium post + }); } From 40db2ef3d8989ee5d37a3351b85a56c9839ed952 Mon Sep 17 00:00:00 2001 From: almenon Date: Sun, 22 Dec 2019 15:11:59 -0800 Subject: [PATCH 04/16] fix relative urls --- exampleOutput.md | 10 +++++----- lib/convertFromUrl.js | 25 +++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/exampleOutput.md b/exampleOutput.md index 27b10b4..c68989c 100644 --- a/exampleOutput.md +++ b/exampleOutput.md @@ -5,13 +5,13 @@ Keeping yourself motivated as a coder ===================================== -[![Almenon](https://miro.medium.com/fit/c/96/96/1*4FAOBq9qVna6uHkxaolTtA.png)](/@almenon214?source=post_page-----a16a6fcf49c7----------------------) +[![Almenon](https://miro.medium.com/fit/c/96/96/1*4FAOBq9qVna6uHkxaolTtA.png)](https://medium.com/@almenon214?source=post_page-----a16a6fcf49c7----------------------) -[Almenon](/@almenon214?source=post_page-----a16a6fcf49c7----------------------) +[Almenon](https://medium.com/@almenon214?source=post_page-----a16a6fcf49c7----------------------) Follow -[Sep 23, 2018](/@almenon214/keeping-yourself-motivated-as-a-coder-a16a6fcf49c7?source=post_page-----a16a6fcf49c7----------------------) · 4 min read +[Sep 23, 2018](https://medium.com/@almenon214/keeping-yourself-motivated-as-a-coder-a16a6fcf49c7?source=post_page-----a16a6fcf49c7----------------------) · 4 min read Programmers probably have one of the most distracting jobs in existence. Their entire workday is spent in front of a computer — a literally endless source of entertainment and pleasure, a limitless virtual heaven. With literally just a click of a button, you could be in another world. You could be slaying dragons. You could be learning about the [great molasses flood of 1919](https://www.damninteresting.com/the-great-molasses-flood-of-1919/). You could literally be doing _anything._ So why do programmers spend their time programming, a hobby that could only be described as exciting by masochistic workaholics? @@ -33,7 +33,7 @@ But if you’re reading this article, maybe you _don’t_ have anything to motiv 2. **Releases.** Your project is a piece of crap. It barely functions, the architecture is horrible, and [you don’t even really know what you’re doing](https://en.wikipedia.org/wiki/Impostor_syndrome). The last thing you want to do is to expose your baby duckling to the public. But at a certain point you have to cut your losses — you can’t just keep on working on something forever, because then you’re going to have burnout. And you may be pleasantly surprised. Maybe people will like it. Worst case scenario, people will hate it, but in the process of shitting all over it they inadvertently give you helpful advice to fix it. In fact, in my experience the detractors are more helpful than the fans, because they will give you actual advice, not just “oh that looks cool”. 3. **Maximize Fun**. Look for more pleasurable and fulfilling fun, rather than lazy and cheap entertainment. For example, it’s far too easy to _control-n_ to open a new tab and type in the letter r to get the autocomplete for reddit. That’s just 3 keys and a enter. Reddit is fun, I love it, but its filled with low effort reposts. Taking the time to watch a show or even a movie might be a better idea — you have a clear chance to stop (at the end) rather than scrolling through reddit’s infinite amount of content. Important disclaimer: _never_ click on netflix’s next episode button. That’s a feature designed by the devil to get you to binge-watch shows and hate yourself afterwards. If you actually have time to watch the next episode then you can wait for the credits to go by. Or more likely, realize what you are doing and go do something productive. 4. **Take walks.** Rest your eyes. Think about how to approach the problem. If you’re me, try reading while walking. It’s not that dangerous — you’ve only bumped into a pole once or twice. -5. **Get the support of others**. Join a slack/discord community. Make a program that other people use. Ask for advice from your friends. Go to programming meetups. Go to [programming conventions](/@almenon214/pycon-2018-6b1c45889e3b) — it’s a great excuse for a vacation, and it’s a lot less dry than it sounds. Go past your normal boundaries — you might be surprised as to what you are capable of. -6. **Add** [**telemetry**](/@almenon214/adding-telemetry-to-your-vscode-extension-f3d52d2e573c) **or** [**alerting**](/@almenon214/setting-up-email-alerts-for-your-vscode-extension-using-azure-d755651b2e0d) **to your program**. It might not be practical for a small application, but it is _extremely_ useful as a motivating tool. Every day I get emails from around the world. People use [AREPL](https://github.com/Almenon/AREPL-vscode) in [New York, Canada, Brazil, Chile. Europe, Japan, Israel, and Pakistan](/@almenon214/arepl-stats-for-june-5e0c87636c3). Every day it’s a different country. It’s significant to know that people are using what I make and relying on me to continue developing it. In a similar vein, I also get emails whenever my reddit bot posts. I can see if people upvote it or if there are problems with the bot I need to fix. +5. **Get the support of others**. Join a slack/discord community. Make a program that other people use. Ask for advice from your friends. Go to programming meetups. Go to [programming conventions](https://medium.com/@almenon214/pycon-2018-6b1c45889e3b) — it’s a great excuse for a vacation, and it’s a lot less dry than it sounds. Go past your normal boundaries — you might be surprised as to what you are capable of. +6. **Add** [**telemetry**](https://medium.com/@almenon214/adding-telemetry-to-your-vscode-extension-f3d52d2e573c) **or** [**alerting**](https://medium.com/@almenon214/setting-up-email-alerts-for-your-vscode-extension-using-azure-d755651b2e0d) **to your program**. It might not be practical for a small application, but it is _extremely_ useful as a motivating tool. Every day I get emails from around the world. People use [AREPL](https://github.com/Almenon/AREPL-vscode) in [New York, Canada, Brazil, Chile. Europe, Japan, Israel, and Pakistan](https://medium.com/@almenon214/arepl-stats-for-june-5e0c87636c3). Every day it’s a different country. It’s significant to know that people are using what I make and relying on me to continue developing it. In a similar vein, I also get emails whenever my reddit bot posts. I can see if people upvote it or if there are problems with the bot I need to fix. Hopefully these tips are helpful to you. If they are, I’d love to hear it. Or maybe you have a tip of your own — either way, leave a comment below! diff --git a/lib/convertFromUrl.js b/lib/convertFromUrl.js index ba62afa..654a216 100644 --- a/lib/convertFromUrl.js +++ b/lib/convertFromUrl.js @@ -8,6 +8,31 @@ const gfm = require('turndown-plugin-gfm').gfm const turndownService = new TurndownService() turndownService.use(gfm) +// following block adapted from https://github.com/domchristie/turndown/blob/61c2748c99fc53699896c1449f953ea492311c5b/src/commonmark-rules.js#L131 +turndownService.addRule('mediumInlineLink', { + filter: function (node, options) { + return ( + options.linkStyle === 'inlined' && + node.nodeName === 'A' && + node.getAttribute('href') + ) + }, + + replacement: function (content, node) { + var href = node.getAttribute('href') + + // following code added in to handle medium relative urls + // otherwise the link to article "foo" in the new website would go to + // https://newwebsite.com/@username/foo-a16a6fcf49c7 which doesn't exist + if(href.startsWith('/')){ + href = "https://medium.com" + href + } + + var title = node.title ? ' "' + node.title + '"' : '' + return '[' + content + '](' + href + title + ')' + } +}) + function convertFromUrl(url) { return new Promise(function(resolve, reject) { request({ From 65592f24c230bed6ff4569a6b0f3c8df0b9c4f71 Mon Sep 17 00:00:00 2001 From: almenon Date: Sun, 22 Dec 2019 15:17:38 -0800 Subject: [PATCH 05/16] updated readme with command line usage --- README.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 918d3d9..1cb1de7 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,27 @@ This module lets you take a medium post and convert it to markdown. -### Usage +### Command Line Usage + +**Setup:** + +1. Install npm if not already installed +2. Clone the repo +3. run `npm install` inside the repo + +**Outputting to command line:** + +`npm run convert https://medium.com/@almenon214/keeping-yourself-motivated-as-a-coder-a16a6fcf49c7` + +Replace the link with the article you want to convert. + +**Outputting to file:** + +`npm run convert https://medium.com/@almenon214/keeping-yourself-motivated-as-a-coder-a16a6fcf49c7 > exampleOutput.md` + +Replace the link with the article you want to convert. + +### API Usage Currently, the module supports getting the markdown from a medium post by URL. From b77384d8e79ac4307f48871dcd918c76c651c37b Mon Sep 17 00:00:00 2001 From: almenon Date: Sun, 22 Dec 2019 15:18:02 -0800 Subject: [PATCH 06/16] update version to 0.0.3 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 64ec2d4..8012c90 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "medium-to-markdown", - "version": "0.0.2", + "version": "0.0.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 174a5ad..3ff17be 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "medium-to-markdown", - "version": "0.0.2", + "version": "0.0.3", "description": "import a medium URL and convert it to markdown", "main": "index.js", "scripts": { From d256e33683f59a449f8245750bf2084fd163e133 Mon Sep 17 00:00:00 2001 From: almenon Date: Sun, 22 Dec 2019 16:35:57 -0800 Subject: [PATCH 07/16] get rid of weird hidden images --- exampleOutput.md | 4 +--- lib/convertFromUrl.js | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/exampleOutput.md b/exampleOutput.md index c68989c..a355ca0 100644 --- a/exampleOutput.md +++ b/exampleOutput.md @@ -1,5 +1,5 @@ -> medium-to-markdown@0.0.2 convert C:\dev\misc\medium-to-markdown +> medium-to-markdown@0.0.3 convert C:\dev\misc\medium-to-markdown > node index.js "https://medium.com/@almenon214/keeping-yourself-motivated-as-a-coder-a16a6fcf49c7" Keeping yourself motivated as a coder @@ -15,8 +15,6 @@ Follow Programmers probably have one of the most distracting jobs in existence. Their entire workday is spent in front of a computer — a literally endless source of entertainment and pleasure, a limitless virtual heaven. With literally just a click of a button, you could be in another world. You could be slaying dragons. You could be learning about the [great molasses flood of 1919](https://www.damninteresting.com/the-great-molasses-flood-of-1919/). You could literally be doing _anything._ So why do programmers spend their time programming, a hobby that could only be described as exciting by masochistic workaholics? -![](https://miro.medium.com/max/60/1*S15R5ty8G-kRGo-ghk2EGA.jpeg?q=20) - Pictured: sticky, sweet, syrupy disaster diff --git a/lib/convertFromUrl.js b/lib/convertFromUrl.js index 654a216..be76587 100644 --- a/lib/convertFromUrl.js +++ b/lib/convertFromUrl.js @@ -33,6 +33,22 @@ turndownService.addRule('mediumInlineLink', { } }) +// Medium has these weird hidden images that are in the html and get rendered +// by turndown. We filter these out. +turndownService.addRule('noHiddenImages', { + filter: function (node, options) { + return ( + node.nodeName === 'IMG' && + node.getAttribute('src') && + node.getAttribute('src').endsWith('?q=20') + ) + }, + + replacement: function () { + return '' + } +}) + function convertFromUrl(url) { return new Promise(function(resolve, reject) { request({ From 26afb4d88bdefc6b8db93cb77bc03615ab75fab6 Mon Sep 17 00:00:00 2001 From: almenon Date: Sun, 22 Dec 2019 16:58:32 -0800 Subject: [PATCH 08/16] add todo --- lib/convertFromUrl.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/convertFromUrl.js b/lib/convertFromUrl.js index be76587..d101f1d 100644 --- a/lib/convertFromUrl.js +++ b/lib/convertFromUrl.js @@ -49,6 +49,13 @@ turndownService.addRule('noHiddenImages', { } }) +// todo: filter out profile header +// (right below title, the div with author profile pic and name and time to read article) +// unfortunately Medium uses randomly generated CSS properties which makes it hard to +// identify the header and strip it out. For example, I could strip the div with +// the class "eq" but the next time medium updated their CSS the div would have +// a different class name and the filter wouldn't work anymore + function convertFromUrl(url) { return new Promise(function(resolve, reject) { request({ From c729d04a7acdd0b94412f85650b65ad12e24462c Mon Sep 17 00:00:00 2001 From: almenon Date: Mon, 23 Dec 2019 22:19:07 -0800 Subject: [PATCH 09/16] add internal vscode files to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index dab4e51..6c7b50b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ # git ignore node_modules/ +.vscode From b6e4e16e60cce1152d2060dce53cbf2899e0b2e9 Mon Sep 17 00:00:00 2001 From: almenon Date: Mon, 23 Dec 2019 22:26:04 -0800 Subject: [PATCH 10/16] add back converters from earlier --- exampleOutput.md | 8 +------- lib/convertFromUrl.js | 7 +++++++ lib/mdConverters.js | 30 ++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 lib/mdConverters.js diff --git a/exampleOutput.md b/exampleOutput.md index a355ca0..031a9d0 100644 --- a/exampleOutput.md +++ b/exampleOutput.md @@ -5,13 +5,7 @@ Keeping yourself motivated as a coder ===================================== -[![Almenon](https://miro.medium.com/fit/c/96/96/1*4FAOBq9qVna6uHkxaolTtA.png)](https://medium.com/@almenon214?source=post_page-----a16a6fcf49c7----------------------) - -[Almenon](https://medium.com/@almenon214?source=post_page-----a16a6fcf49c7----------------------) - -Follow - -[Sep 23, 2018](https://medium.com/@almenon214/keeping-yourself-motivated-as-a-coder-a16a6fcf49c7?source=post_page-----a16a6fcf49c7----------------------) · 4 min read +[![Almenon](https://miro.medium.com/fit/c/96/96/1*4FAOBq9qVna6uHkxaolTtA.png)](https://medium.com/@almenon214?source=post_page-----a16a6fcf49c7----------------------)[Almenon](https://medium.com/@almenon214?source=post_page-----a16a6fcf49c7----------------------)Follow[Sep 23, 2018](https://medium.com/@almenon214/keeping-yourself-motivated-as-a-coder-a16a6fcf49c7?source=post_page-----a16a6fcf49c7----------------------) · 4 min read Programmers probably have one of the most distracting jobs in existence. Their entire workday is spent in front of a computer — a literally endless source of entertainment and pleasure, a limitless virtual heaven. With literally just a click of a button, you could be in another world. You could be slaying dragons. You could be learning about the [great molasses flood of 1919](https://www.damninteresting.com/the-great-molasses-flood-of-1919/). You could literally be doing _anything._ So why do programmers spend their time programming, a hobby that could only be described as exciting by masochistic workaholics? diff --git a/lib/convertFromUrl.js b/lib/convertFromUrl.js index d101f1d..3ef94e9 100644 --- a/lib/convertFromUrl.js +++ b/lib/convertFromUrl.js @@ -5,9 +5,16 @@ const cheerio = require('cheerio'); const TurndownService = require('turndown') const gfm = require('turndown-plugin-gfm').gfm +const converters = require('./mdConverters'); + + const turndownService = new TurndownService() turndownService.use(gfm) +converters.forEach((converter)=>{ + turndownService.addRule(converter.filter, converter) +}) + // following block adapted from https://github.com/domchristie/turndown/blob/61c2748c99fc53699896c1449f953ea492311c5b/src/commonmark-rules.js#L131 turndownService.addRule('mediumInlineLink', { filter: function (node, options) { diff --git a/lib/mdConverters.js b/lib/mdConverters.js new file mode 100644 index 0000000..2b5e646 --- /dev/null +++ b/lib/mdConverters.js @@ -0,0 +1,30 @@ +'use strict'; + +const converters = [ + { + filter: 'section', + replacement: function(content) { + return content; + } + }, + { + filter: 'div', + replacement: function(content) { + return content; + } + }, + { + filter: 'figure', + replacement: function(content) { + return content; + } + }, + { + filter: 'figcaption', + replacement: function(content) { + return content; + } + }, +] + +module.exports = converters \ No newline at end of file From 5b89df0e70b91c1b0745408f69ca6d77b3a080e5 Mon Sep 17 00:00:00 2001 From: almenon Date: Mon, 23 Dec 2019 22:31:12 -0800 Subject: [PATCH 11/16] minor changes to make git diff better --- lib/mdConverters.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/mdConverters.js b/lib/mdConverters.js index 2b5e646..d6a2aeb 100644 --- a/lib/mdConverters.js +++ b/lib/mdConverters.js @@ -24,7 +24,7 @@ const converters = [ replacement: function(content) { return content; } - }, -] + } +]; -module.exports = converters \ No newline at end of file +module.exports = converters From 7802f01c19e060a4bc43040eb5c58afc9d7a2702 Mon Sep 17 00:00:00 2001 From: almenon Date: Mon, 23 Dec 2019 22:53:15 -0800 Subject: [PATCH 12/16] add example with code blocks --- exampleOutputWithCodeBlocks.md | 68 ++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 exampleOutputWithCodeBlocks.md diff --git a/exampleOutputWithCodeBlocks.md b/exampleOutputWithCodeBlocks.md new file mode 100644 index 0000000..b9c21b5 --- /dev/null +++ b/exampleOutputWithCodeBlocks.md @@ -0,0 +1,68 @@ + +> medium-to-markdown@0.0.3 convert C:\dev\misc\medium-to-markdown +> node index.js "https://medium.com/@almenon214/adding-telemetry-to-your-vscode-extension-f3d52d2e573c" + +Adding telemetry to your vscode extension +========================================= + +[![Almenon](https://miro.medium.com/fit/c/96/96/1*4FAOBq9qVna6uHkxaolTtA.png)](https://medium.com/@almenon214?source=post_page-----f3d52d2e573c----------------------)[Almenon](https://medium.com/@almenon214?source=post_page-----f3d52d2e573c----------------------)Follow[May 6, 2018](https://medium.com/@almenon214/adding-telemetry-to-your-vscode-extension-f3d52d2e573c?source=post_page-----f3d52d2e573c----------------------) · 3 min read + +The [1% rule](https://en.wikipedia.org/wiki/1%25_rule_(Internet_culture)) of the internet states that the vast majority of users do not engage with the content — they use it and see it, but leave no feedback. In some cases they might give your product one try, don’t like it, and never come back. Or not even try it! This lack of feedback makes it very hard to improve your product or market it to new users. + +Enter telemetry — by automatically collecting statistics and/or errors, you can get feedback without having to conduct expensive market research. + +[Azure application insights](https://azure.microsoft.com/en-us/services/application-insights/) makes this collection very simple (and free): + +npm install [vscode-extension-telemetry](https://github.com/Microsoft/vscode-extension-telemetry) --save + +If you want a real-world example of its useage you can take a look at how I use it in [AREPL-vscode](https://github.com/Almenon/AREPL-vscode/blob/master/src/telemetry.ts). + +Once it is working you should see events appear in the metrics explorer in azure: + + + +But the beauty of application insights is not just in the logging — Microsoft offers a sophistacted query language, similar to SQL / Splunk. + + + +distinct users, ordered by last use date. + +Some other useful queries: + +// heaviest users by avg time spent using extcustomEvents | +where timestamp < now() and name=="almenon.arepl/closed" | +summarize timeOpen=avg(todouble(customDimensions.timeSpent)) by cloud\_RoleInstance | order by timeOpen + +* * * + +// most frequent users by number of times openedcustomEvents | +where timestamp < now() and name=="almenon.arepl/closed" | +summarize numEvents=count(iKey) by cloud\_RoleInstance | order by numEvents + +* * * + +You can even project your results into graphs + +customEvents | where name == 'almenon.arepl/closed' | summarize count() by client\_CountryOrRegion | render piechart + + + +The analysis leads to some interesting conclusions: + +1. Despite having hundreds of downloads, the actual user count is much much lower. 5 people have used it so far with one person using it twice… not great statistics. Should pick up once I market AREPL at pycon. +2. The range of users is quite geographically diverse. You don’t just get people in California or America; there’s people from canada, italy, portugal, all sorts of places. I guess that is to be expected with internet marketing — people can see your extension from countries across the world. + +Once I get more people using the extension I should be able to draw more insights — like what settings they change, for example. Or how often errors occur. Or the most popular time the extension is used. Really, sky’s the limit! + +**Update:** further anlysis of my telemetry data can be found at: + +[ + +AREPL stats for June +-------------------- + +### So about a month ago I added telemetry to AREPL-vscode to get an idea of how my user base was doing. The information I… + +#### medium.com + +](https://medium.com/@almenon214/arepl-stats-for-june-5e0c87636c3) From 0f6997f01bcf64bf9fe4664eba3b0a952a86bacb Mon Sep 17 00:00:00 2001 From: almenon Date: Mon, 23 Dec 2019 22:54:37 -0800 Subject: [PATCH 13/16] move examples to folder --- exampleOutput.md => examples/exampleOutput.md | 0 .../exampleOutputWithCodeBlocks.md | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename exampleOutput.md => examples/exampleOutput.md (100%) rename exampleOutputWithCodeBlocks.md => examples/exampleOutputWithCodeBlocks.md (100%) diff --git a/exampleOutput.md b/examples/exampleOutput.md similarity index 100% rename from exampleOutput.md rename to examples/exampleOutput.md diff --git a/exampleOutputWithCodeBlocks.md b/examples/exampleOutputWithCodeBlocks.md similarity index 100% rename from exampleOutputWithCodeBlocks.md rename to examples/exampleOutputWithCodeBlocks.md From 2ed277dd96a1adcc98f40532e1ede41917d2c552 Mon Sep 17 00:00:00 2001 From: almenon Date: Mon, 23 Dec 2019 22:54:56 -0800 Subject: [PATCH 14/16] add genExample command --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 3ff17be..932c337 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "main": "index.js", "scripts": { "convert": "node index.js", - "test": "echo \"Error: no test specified\" && exit 1" + "test": "echo \"Error: no test specified\" && exit 1", + "genExample": "npm run convert https://medium.com/@almenon214/keeping-yourself-motivated-as-a-coder-a16a6fcf49c7 > examples/exampleOutput.md" }, "author": "SkillFlow, Inc.", "license": "MIT", From 2e7c94c970867bcf19c088a734089b1bb14bcbc3 Mon Sep 17 00:00:00 2001 From: almenon Date: Mon, 23 Dec 2019 22:55:37 -0800 Subject: [PATCH 15/16] add backticks for code blocks --- examples/exampleOutputWithCodeBlocks.md | 8 ++++++++ lib/convertFromUrl.js | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/examples/exampleOutputWithCodeBlocks.md b/examples/exampleOutputWithCodeBlocks.md index b9c21b5..8dd4715 100644 --- a/examples/exampleOutputWithCodeBlocks.md +++ b/examples/exampleOutputWithCodeBlocks.md @@ -13,7 +13,9 @@ Enter telemetry — by automatically collecting statistics and/or errors, you ca [Azure application insights](https://azure.microsoft.com/en-us/services/application-insights/) makes this collection very simple (and free): +``` npm install [vscode-extension-telemetry](https://github.com/Microsoft/vscode-extension-telemetry) --save +``` If you want a real-world example of its useage you can take a look at how I use it in [AREPL-vscode](https://github.com/Almenon/AREPL-vscode/blob/master/src/telemetry.ts). @@ -29,21 +31,27 @@ distinct users, ordered by last use date. Some other useful queries: +``` // heaviest users by avg time spent using extcustomEvents | where timestamp < now() and name=="almenon.arepl/closed" | summarize timeOpen=avg(todouble(customDimensions.timeSpent)) by cloud\_RoleInstance | order by timeOpen +``` * * * +``` // most frequent users by number of times openedcustomEvents | where timestamp < now() and name=="almenon.arepl/closed" | summarize numEvents=count(iKey) by cloud\_RoleInstance | order by numEvents +``` * * * You can even project your results into graphs +``` customEvents | where name == 'almenon.arepl/closed' | summarize count() by client\_CountryOrRegion | render piechart +``` diff --git a/lib/convertFromUrl.js b/lib/convertFromUrl.js index 3ef94e9..98873bf 100644 --- a/lib/convertFromUrl.js +++ b/lib/convertFromUrl.js @@ -56,6 +56,13 @@ turndownService.addRule('noHiddenImages', { } }) +turndownService.addRule('code blocks', { + filter: 'pre', + replacement: function (content, node) { + return "```\n" + content + "\n```" + } +}) + // todo: filter out profile header // (right below title, the div with author profile pic and name and time to read article) // unfortunately Medium uses randomly generated CSS properties which makes it hard to From cd4cb1b116b8b297b39f4a4c16db09dff4408dca Mon Sep 17 00:00:00 2001 From: almenon Date: Mon, 23 Dec 2019 22:55:57 -0800 Subject: [PATCH 16/16] add note on examples to readme --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 1cb1de7..40beff3 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,10 @@ Replace the link with the article you want to convert. Replace the link with the article you want to convert. +### What does the output look like? + +See `examples/exampleOutput.md` for an example of what https://medium.com/@almenon214/keeping-yourself-motivated-as-a-coder-a16a6fcf49c7 looks like when converted to markdown. + ### API Usage Currently, the module supports getting the markdown from a medium post by URL.