Skip to content

Instantly share code, notes, and snippets.

@malys
Last active January 18, 2022 09:32
Show Gist options
  • Save malys/bda40629445f12e5a3bcb90a81daab63 to your computer and use it in GitHub Desktop.
Save malys/bda40629445f12e5a3bcb90a81daab63 to your computer and use it in GitHub Desktop.
[Mark preprocessing] plantuml and external file insertion #md #confluence #plantuml #mark
/*
Prerequisites:
* Plantuml + Java
* Mark
* npm i -g zx
* zx markExport.mjs "password"
<!-- Attachment: ./release_stable.puml.png --> => generate automatically image from release_stable.puml
<!-- file://D:/example.js;10;12 --> => insert code snippets
*/
const args = process.argv;
const password = args[3];
const FOLDER = 'D:/Developpement/archi/all-modules/documentation';
const PLANTUML = "D:/prog/plantuml.jar";
$.verbose = false
const DRY_RUN = process.env.MARK_DRY_RUN;
let dryRun = "";
if (DRY_RUN) {
dryRun = '--dry-run';
}
const FILTER = process.env.MARK_FILTER;
const TRACE = process.env.MARK_TRACE;
let trace = "";
if (TRACE) {
trace = "--trace";
$.verbose = true;
}
const DEBUG = process.env.MARK_DEBUG;
let debug = "";
if (DEBUG) {
debug = "--debug";
$.verbose = true;
}
function escapeRegex(string) {
return string.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}
function getPath(root, file) {
if (file.startsWith(".")) {
//relative
return path.join(root, file).replace(/\\/g, '/');
} else {
return file;
}
}
async function includeFile(root, content) {
let m;
const regex = /<!-- file:\/\/(.*)\W*-->/gm;
while ((m = regex.exec(content)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
let tag = m[1]
let parameters = tag.split(';');
let lines;
let file = parameters[0].trim();
let extension = path.extname(file).substring(1);
let contentToInsert = fs.readFileSync(getPath(path.dirname(root), file), 'utf-8');
if (parameters.length > 2) {
let begin = parameters[1];
let end = parameters[2];
lines = contentToInsert.split('\n').slice(begin - 1, end - 1);
} else {
lines = contentToInsert.split('\n');
}
const first = content.indexOf("<!-- file:\/\/" + tag);
let last;
if (content.indexOf("```" + extension, first + 1) !== -1 && Math.abs(content.indexOf("```" + extension, first + 1) - content.indexOf("-->", first + 1)) < 10) {
last = content.indexOf("```\n", first + 1) + 4;
} else {
last = content.indexOf("-->", first + 1) + 3;
}
if (last !== -1) {
const toReplace = content.substring(first, last);
const subst = "<!-- file://" + tag + "-->\n```" + extension + "\n" + lines.join('\n') + "\n```\n";
content = content.replace(toReplace, subst);
}
//console.log(regexp, content.match(regex2),content);
}
return content;
}
async function attachment(root, content) {
//<!-- Attachment: <path-to-image> -->
let m;
const regex = /<!-- Attachment: (.*) -->/gm;
while ((m = regex.exec(content)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
let tag = path.join(path.dirname(root), m[1]);
if (tag.trim().endsWith(".puml.png")) {
let output = path.dirname(tag);
let fileName = path.basename(tag, ".png");
let basename = path.basename(fileName, ".puml");
let cmd = `java -jar "${PLANTUML}" "${path.join(output,fileName)}" -overwrite -checkmetadata -o "${output}"`
await $([cmd]);
await fs.rename(path.join(output, basename + '.png'), path.join(output, basename + '.puml.png'));
}
}
return content;
}
async function attachmentCheck(root, content) {
//<!-- Attachment: <path-to-image> -->
let m;
const regex = /<!-- Attachment: (.*) -->/gm;
while ((m = regex.exec(content)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
let tag = path.join(path.dirname(root), m[1]);
if (/\d/.test(tag)) {
console.error('--> Attachment has not to contain a digit ' + tag + ' <--');
}
}
}
async function analyse(file) {
let content = fs.readFileSync(file, 'utf-8');
let toWrite = false;
if (content.indexOf('<!-- file://') > -1) {
//Include external file
content = await includeFile(file, content);
toWrite = true || toWrite;
}
if (content.indexOf('Attachment' > -1)) {
//Include external file
await attachmentCheck(file, content);
toWrite = false || toWrite;
}
if (content.indexOf('.puml.png' > -1)) {
//Include external file
content = await attachment(file, content);
toWrite = false || toWrite;
}
if (toWrite) fs.writeFileSync(file, content);
}
(async () => {
cd(FOLDER)
let mds = await globby([FOLDER + '/**/*.md']);
mds = mds.filter(f => f.toUpperCase().indexOf('README') === -1);
mds = mds.filter(f => !f.toUpperCase().endsWith('_TMP.MD'));
if (FILTER) {
mds = mds.filter(f => f.toUpperCase().indexOf(FILTER.toUpperCase()) !== -1);
}
mds=mds.sort((a,b)=>{
return a.localeCompare(b);
})
//TODO avec filter modified files "git status -s"
for (let index = 0; index < mds.length; index++) {
let md = mds[index];
await analyse(md);
console.info('--> Processing:' + md)
try {
cd(path.dirname(md));
if (md.toUpperCase().indexOf('README') == -1) {
let cmd = `mark -u ${process.env.USERNAME} -b https://${process.env.CONFLUENCE} -p "${password}" -f ${md} --drop-h1 ${dryRun} ${trace} ${debug}`
let result = await $([cmd]);
console.log(result.stderr)
}
} catch (e) {
console.error(e);
}
}
if(mds.length === 0) {
console.log('No markdown files to process');
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment