diff --git a/packages/ajax/package.json b/packages/ajax/package.json index 0131bdcb4c..1a46d8a250 100644 --- a/packages/ajax/package.json +++ b/packages/ajax/package.json @@ -14,7 +14,7 @@ "directory": "packages/ajax" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/button/package.json b/packages/button/package.json index 5b087cf6e5..98469d5ae9 100644 --- a/packages/button/package.json +++ b/packages/button/package.json @@ -14,7 +14,7 @@ "directory": "packages/button" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/checkbox-group/package.json b/packages/checkbox-group/package.json index 1498b1a660..5cc927ec6c 100644 --- a/packages/checkbox-group/package.json +++ b/packages/checkbox-group/package.json @@ -14,7 +14,7 @@ "directory": "packages/checkbox-group" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/checkbox/package.json b/packages/checkbox/package.json index 3f5d6dc4a1..1039328a62 100644 --- a/packages/checkbox/package.json +++ b/packages/checkbox/package.json @@ -14,7 +14,7 @@ "directory": "packages/checkbox" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/choice-input/package.json b/packages/choice-input/package.json index 836c287440..6bc019ec1a 100644 --- a/packages/choice-input/package.json +++ b/packages/choice-input/package.json @@ -14,7 +14,7 @@ "directory": "packages/choice-input" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/core/package.json b/packages/core/package.json index 6a6913e7d4..849a441ee4 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -14,7 +14,7 @@ "directory": "packages/core" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/field/package.json b/packages/field/package.json index 4388a64756..bc77777f87 100644 --- a/packages/field/package.json +++ b/packages/field/package.json @@ -14,7 +14,7 @@ "directory": "packages/field" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/fieldset/package.json b/packages/fieldset/package.json index acd34ce9af..3396845c6c 100644 --- a/packages/fieldset/package.json +++ b/packages/fieldset/package.json @@ -14,7 +14,7 @@ "directory": "packages/fieldset" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/form-system/package.json b/packages/form-system/package.json index 8bba731db5..8d37d7b1cc 100644 --- a/packages/form-system/package.json +++ b/packages/form-system/package.json @@ -14,7 +14,7 @@ "directory": "packages/form-system" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/form/package.json b/packages/form/package.json index a7ca7bf3cd..4878c7ba44 100644 --- a/packages/form/package.json +++ b/packages/form/package.json @@ -14,7 +14,7 @@ "directory": "packages/form" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/icon/package.json b/packages/icon/package.json index 414edd7830..bfe2bdf1ce 100644 --- a/packages/icon/package.json +++ b/packages/icon/package.json @@ -14,7 +14,7 @@ "directory": "packages/icon" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/input-amount/package.json b/packages/input-amount/package.json index bdf0556aac..629106621a 100644 --- a/packages/input-amount/package.json +++ b/packages/input-amount/package.json @@ -14,7 +14,7 @@ "directory": "packages/input-amount" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/input-date/package.json b/packages/input-date/package.json index 2e750b2179..4d72590069 100644 --- a/packages/input-date/package.json +++ b/packages/input-date/package.json @@ -14,7 +14,7 @@ "directory": "packages/input-date" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/input-email/package.json b/packages/input-email/package.json index dbe74e9d23..56e540865a 100644 --- a/packages/input-email/package.json +++ b/packages/input-email/package.json @@ -14,7 +14,7 @@ "directory": "packages/input-email" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/input-iban/package.json b/packages/input-iban/package.json index 6e03fd60d7..42b34f58cf 100644 --- a/packages/input-iban/package.json +++ b/packages/input-iban/package.json @@ -14,7 +14,7 @@ "directory": "packages/input-iban" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/input/package.json b/packages/input/package.json index e23d09b246..6de0eab915 100644 --- a/packages/input/package.json +++ b/packages/input/package.json @@ -14,7 +14,7 @@ "directory": "packages/input" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/localize/package.json b/packages/localize/package.json index 15d3a7836c..3f9ca93277 100644 --- a/packages/localize/package.json +++ b/packages/localize/package.json @@ -14,7 +14,7 @@ "directory": "packages/localize" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/overlays/package.json b/packages/overlays/package.json index d81c19f8eb..d8185d014b 100644 --- a/packages/overlays/package.json +++ b/packages/overlays/package.json @@ -14,7 +14,7 @@ "directory": "packages/overlays" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/popup/package.json b/packages/popup/package.json index fbaa6c60ff..5e99cd8f1d 100644 --- a/packages/popup/package.json +++ b/packages/popup/package.json @@ -14,7 +14,7 @@ "directory": "packages/popup" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/radio-group/package.json b/packages/radio-group/package.json index 620aef96dd..90489cb6b3 100644 --- a/packages/radio-group/package.json +++ b/packages/radio-group/package.json @@ -14,7 +14,7 @@ "directory": "packages/radio-group" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/radio/package.json b/packages/radio/package.json index 44c1ea19ec..6766892c06 100644 --- a/packages/radio/package.json +++ b/packages/radio/package.json @@ -14,7 +14,7 @@ "directory": "packages/radio" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/select/package.json b/packages/select/package.json index 75fc7e68cf..596e27ac2b 100644 --- a/packages/select/package.json +++ b/packages/select/package.json @@ -14,7 +14,7 @@ "directory": "packages/select" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/steps/package.json b/packages/steps/package.json index 14645ed712..f893848085 100644 --- a/packages/steps/package.json +++ b/packages/steps/package.json @@ -14,7 +14,7 @@ "directory": "packages/steps" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/textarea/package.json b/packages/textarea/package.json index ce37028820..22fdbdb0e5 100644 --- a/packages/textarea/package.json +++ b/packages/textarea/package.json @@ -14,7 +14,7 @@ "directory": "packages/textarea" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/tooltip/package.json b/packages/tooltip/package.json index 1a61694f7e..6b072ec89c 100644 --- a/packages/tooltip/package.json +++ b/packages/tooltip/package.json @@ -14,7 +14,7 @@ "directory": "packages/tooltip" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/packages/validate/package.json b/packages/validate/package.json index be319beb6b..aa0d392717 100644 --- a/packages/validate/package.json +++ b/packages/validate/package.json @@ -14,7 +14,7 @@ "directory": "packages/validate" }, "scripts": { - "prepublishOnly": "../../scripts/insert-header.js" + "prepublishOnly": "../../scripts/npm-prepublish.js" }, "keywords": [ "lion", diff --git a/scripts/insert-header.js b/scripts/insert-header.js index c6a6b57ecd..3fc2915782 100755 --- a/scripts/insert-header.js +++ b/scripts/insert-header.js @@ -1,5 +1,3 @@ -#!/usr/bin/env node - /* eslint-disable consistent-return, no-console */ const fs = require('fs'); diff --git a/scripts/npm-prepublish.js b/scripts/npm-prepublish.js new file mode 100755 index 0000000000..c6ffba42e8 --- /dev/null +++ b/scripts/npm-prepublish.js @@ -0,0 +1,7 @@ +#!/usr/bin/env node + +// insert headers in README.md +require('./insert-header.js'); + +// rewrite relative markdown documentation links to absolute Github links +require('./rewrite-links.js')(); diff --git a/scripts/rewrite-links.js b/scripts/rewrite-links.js new file mode 100644 index 0000000000..b79bbd3ef5 --- /dev/null +++ b/scripts/rewrite-links.js @@ -0,0 +1,122 @@ +/** + * Before we publish to npm, we want to rewrite all relative links inside markdown files to + * absolute github paths, so that documentation hosted on npmjs.com never contains broken links. + */ + +const fs = require('fs'); +const path = require('path'); + +const rewriteLinksConfig = { + githubPath: 'https://github.com/ing-bank/lion/blob/master/', + monorepoRootPath: path.resolve(__dirname, '../'), +}; + +const gatherFilesConfig = { + extension: '.md', + excludeFiles: ['CHANGELOG.md'], + excludeFolders: ['node_modules', '.history'], +}; + +/** + * Gets an array of files for given extension + * @param {string} startPath - local filesystem path + * @param {object} cfg - configuration object + * @param {string} cfg.extension - file extension like '.md' + * @param {array} cfg.excludeFiles - file names filtered out + * @param {array} cfg.excludeFolders - folder names filtered out + * @param {array} result - list of file paths + * @returns {array} result list of file paths + */ +function gatherFilesFromDir(startPath, cfg = gatherFilesConfig, result = []) { + const files = fs.readdirSync(startPath); + files.forEach(file => { + const filePath = path.join(startPath, file); + const stat = fs.lstatSync(filePath); + if (stat.isDirectory()) { + const folderName = filePath.replace(/.*\/([^/]+)$/, '$1'); + if (!cfg.excludeFolders.includes(folderName)) { + gatherFilesFromDir(filePath, cfg, result); // search recursively + } + } else if (filePath.endsWith(cfg.extension)) { + const fileName = filePath.replace(/.*\/([^/]+)$/, '$1'); + if (!cfg.excludeFiles.includes(fileName)) { + result.push(filePath); + } + } + }); + return result; +} + +/** + * Rewrites all relative links of markdown content to absolute links. + * Also includes images. See: https://github.com/tcort/markdown-link-extractor/blob/master/index.js + * @param {string} mdContent - contents of .md file to parse + * @param {string} filePath - local filesystem path of md file, + * like '/path/to/lion/packages/my-component/docs/myClass.md' + * @param {object} cfg - configurantion object + * @param {string} cfg.githubPath - root github url for the absolute result links + * @param {string} cfg.monorepoRootPath - local filesystem root path of the monorepo + * @returns {string} adjusted contents of input md file (mdContent) + */ +function rewriteLinksInMdContent(mdContent, filePath, cfg = rewriteLinksConfig) { + const rewrite = href => { + let newHref = href; + const isRelativeUrlPattern = /^(\.\/|\.\.\/)/; // starts with './' or '../' + if (href.match(isRelativeUrlPattern)) { + const fileFolder = filePath.replace(/(.*\/).*/g, '$1'); + const absoluteLocalPath = path.resolve(fileFolder, href); + // relativeFromRootPath: for instance 'packages/my-component/docs/' when + // filePath is 'path/to/repo/packages/my-component/docs/myDoc.md' + const relativeFromRootPath = absoluteLocalPath.replace(cfg.monorepoRootPath, '').slice(1); + // newRoot: https://github.com/ing-bank/lion/blob/master/packages/my-component/docs/ + newHref = cfg.githubPath + relativeFromRootPath; + } + return newHref; + }; + + const mdLink = (href, title, text) => { + return `[${text}](${rewrite(href)}${title ? ` ${title}` : ''})`; + }; + + const resultLinks = []; + // /^!?\[(label)\]\(href(?:\s+(title))?\s*\)/ + const linkPattern = '!?\\[(.*)\\]\\(([^|\\s]*)( +(.*))?\\s*\\)'; // eslint-disable-line + const matches = mdContent.match(new RegExp(linkPattern, 'g')) || []; + + matches.forEach(link => { + let newLink = ''; + const parts = link.match(new RegExp(linkPattern)); + if (parts) { + newLink = mdLink(parts[2], parts[3], parts[1]); + } + resultLinks.push(newLink); + }); + + // Now that we have our rewritten links, stitch back together the desired result + const tokenPattern = /!?\[.*\]\([^|\s]*(?: +.*)?\s*\)/; + const tokens = mdContent.split(new RegExp(tokenPattern, 'g')); + const resultTokens = []; + tokens.forEach((token, i) => { + resultTokens.push(token + (resultLinks[i] || '')); + }); + const resultContent = resultTokens.join(''); + return resultContent; +} + +/** + * Main code + */ +function main({ dryRun } = { dryRun: false }) { + const mdFilePaths = gatherFilesFromDir(process.cwd()); // [path.resolve(__dirname, '../', 'packages/field/README.md')]; + mdFilePaths.forEach(filePath => { + const content = fs.readFileSync(filePath).toString(); + const rewrittenContent = rewriteLinksInMdContent(content, filePath); + if (dryRun) { + console.log(`== output for filePath '${filePath}' ===`); // eslint-disable-line no-console + console.log(rewrittenContent); // eslint-disable-line no-console + } else { + fs.writeFileSync(filePath, rewrittenContent); + } + }); +} +module.exports = main;