Skip to content

Instantly share code, notes, and snippets.

@vsemozhetbyt
Last active January 17, 2017 21:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vsemozhetbyt/d714bf98f4235a77db923e1c8744bc1b to your computer and use it in GitHub Desktop.
Save vsemozhetbyt/d714bf98f4235a77db923e1c8744bc1b to your computer and use it in GitHub Desktop.
Extract JavaScript fragments from a markdown file
'use strict';
const fs = require('fs');
const path = require('path');
const rl = require('readline');
const [, , mdFilePath] = process.argv;
const jsDirPath = path.join(
path.dirname(mdFilePath),
`${path.basename(mdFilePath)}.extracted-js`
);
fs.mkdirSync(jsDirPath);
const rli = rl.createInterface({
input: fs.createReadStream(mdFilePath, 'utf8'),
});
const jsFragments = [];
const jsFragmentStart = /^(\s*)```(?:js|javascript)\s*$/i;
const jsFragmentEnd = /^\s*```\s*$/;
let lineNumber = 0;
let inJsFragment = false;
let initialIndentation;
rli.on('line', (line) => {
lineNumber++;
if (jsFragmentStart.test(line) && !inJsFragment) {
inJsFragment = true;
initialIndentation = new RegExp(`^${line.match(jsFragmentStart)[1]}`);
jsFragments.push({ startLine: lineNumber + 1, endLine: undefined, js: '' });
} else if (jsFragmentEnd.test(line) && inJsFragment) {
inJsFragment = false;
jsFragments[jsFragments.length - 1].endLine = lineNumber - 1;
} else if (inJsFragment) {
jsFragments[jsFragments.length - 1].js += `${line.replace(initialIndentation, '')}\n`;
}
}).on('close', () => {
const lastEndLineNumber = jsFragments[jsFragments.length - 1].endLine;
jsFragments.forEach((jsFragment, i) => {
jsFragment.startLine = padLeft(jsFragment.startLine, lastEndLineNumber);
jsFragment.endLine = padLeft(jsFragment.endLine, lastEndLineNumber);
const jsFileName = `${
padLeft(i + 1, jsFragments.length)
}.${jsFragment.startLine}-${jsFragment.endLine}.js`;
fs.writeFileSync(
path.join(jsDirPath, jsFileName),
`\uFEFF'use strict';
// ${
jsFragment.startLine === jsFragment.endLine ?
jsFragment.startLine :
`${jsFragment.startLine} – ${jsFragment.endLine}`
}
${jsFragment.js}`,
'utf8'
);
});
});
function padLeft(padNumber, edgeNumber) {
return `${
'0'.repeat(String(edgeNumber).length - String(padNumber).length)
}${padNumber}`;
}
@vsemozhetbyt
Copy link
Author

vsemozhetbyt commented Jan 11, 2017

Usage: md.extract-js.js markdown-file.md.

Extracted .js files will be created in the markdown-file.md.extracted-js directory next to markdown-file.md. Each file has this name template: numberOfFragment.numberOfFirstLine-numberOfLastLine.js.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment