From d67845db05b6f82410c57d453eb3de1251d8f07e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20J=C3=BCtte?= Date: Thu, 17 Apr 2025 19:09:42 +0200 Subject: [PATCH 1/2] add options to keep metadata from either old or new file or none of them --- README.md | 1 + src/cli.ts | 1 + src/index.ts | 40 +++++++++++++++++++++++++++++++++++----- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 575f8cb..c4a733e 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,7 @@ Usage: pandiff [OPTIONS] FILE1 FILE2 -t, --to=FORMAT -v, --version --wrap=STRING + --metadata ``` ### Git integration diff --git a/src/cli.ts b/src/cli.ts index df2f5a7..f4c2ff4 100755 --- a/src/cli.ts +++ b/src/cli.ts @@ -54,6 +54,7 @@ const optionDefinitions: commandLineArgs.OptionDefinition[] = [ {name: 'version', alias: 'v', type: Boolean}, {name: 'wrap', type: String}, {name: 'files', multiple: true, defaultOption: true}, + {name: 'metadata', type: String}, ]; function help() { diff --git a/src/index.ts b/src/index.ts index f6203a3..3ae4d8f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -263,11 +263,36 @@ async function convert(source: string, opts: pandiff.Options = {}) { return html; } +async function extractMetadata(source: string) { + const file = fs.readFileSync(source, 'utf8'); + const lines = file.split('\n'); + if (lines[0].trim() !== '---') return ''; + + const metadata = [lines[0]]; + for (let i = 1; i < lines.length; i++) { + metadata.push(lines[i]); + if (lines[i].trim() === '---') break; + } + + return metadata.join('\n'); +} + async function pandiff( source1: string, source2: string, opts: pandiff.Options = {} ): Promise { + let metadata = ''; + switch (opts.metadata) { + case 'old': + metadata = await extractMetadata(source1); + break; + case 'new': + metadata = await extractMetadata(source2); + break; + default: + break; + } const html1 = await convert(source1, opts); const html2 = await convert(source2, opts); const html = htmldiff(html1, html2); @@ -282,7 +307,7 @@ async function pandiff( ); return null; } else { - return render(html, opts); + return render(html, opts, metadata); } } @@ -319,7 +344,7 @@ const regex = { }, }; -async function render(html: string, opts: pandiff.Options = {}) { +async function render(html: string, opts: pandiff.Options = {}, metadata = '') { html = postprocess(html); const args = buildArgs(opts, 'reference-links'); args.push('--wrap=none'); @@ -357,7 +382,7 @@ async function render(html: string, opts: pandiff.Options = {}) { } } const text = lines.join('\n'); - return postrender(text, opts); + return postrender(text, opts, metadata); } const criticHTML = (text: string) => @@ -411,7 +436,11 @@ const pandocOptionsHTML = [ '--standalone', ]; -async function postrender(text: string, opts: pandiff.Options = {}) { +async function postrender( + text: string, + opts: pandiff.Options = {}, + metadata = '' +) { if (!opts.output && !opts.to) return text; if (!('highlight-style' in opts)) opts['highlight-style'] = 'kate'; @@ -447,7 +476,7 @@ async function postrender(text: string, opts: pandiff.Options = {}) { } if (opts.output) { - await sh.pandoc(...args).end(text); + await sh.pandoc(...args).end(`${metadata}\n${text}`); return null; } else { return sh @@ -484,6 +513,7 @@ namespace pandiff { // eslint-disable-line version?: boolean; wrap?: 'auto' | 'none' | 'preserve'; files?: boolean; + metadata?: 'new' | 'old' | 'none'; } /* eslint-disable no-inner-declarations */ export async function trackChanges( From ffab700b56128026a82306bfc26a26d8eb0794d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20J=C3=BCtte?= Date: Mon, 5 May 2025 22:24:07 +0200 Subject: [PATCH 2/2] keep metadata when converting from md to md; add some tests for metadata --- .gitignore | 1 + src/index.spec.ts | 81 ++++++++++++++++++++++++++++++++++ src/index.ts | 14 +++--- test/keep-new-metadata-diff.md | 15 +++++++ test/keep-no-metadata-diff.md | 11 +++++ test/keep-old-metadata-diff.md | 15 +++++++ test/new-metadata.md | 6 +++ test/old-metadata.md | 6 +++ 8 files changed, 144 insertions(+), 5 deletions(-) create mode 100644 test/keep-new-metadata-diff.md create mode 100644 test/keep-no-metadata-diff.md create mode 100644 test/keep-old-metadata-diff.md create mode 100644 test/new-metadata.md create mode 100644 test/old-metadata.md diff --git a/.gitignore b/.gitignore index a23a04d..42ee49f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ node_modules/ lib/ .mocharc.yml *.pdf +test/*.actual diff --git a/src/index.spec.ts b/src/index.spec.ts index 78c91a4..998f391 100644 --- a/src/index.spec.ts +++ b/src/index.spec.ts @@ -159,3 +159,84 @@ describe('Misc', () => { expectWithFallback(output, expected, 'test/diff-table.html'); }); }); + +describe('Metadata', () => { + it('keep metadata from old document', async () => { + const output = await pandiff( + 'test/old-metadata.md', + 'test/new-metadata.md', + { + files: true, + metadata: 'old', + to: 'markdown', + } + ); + const expected = fs.readFileSync('test/keep-old-metadata-diff.md', 'utf8'); + expect(output, expected); + }); + it('keep metadata from new document', async () => { + const output = await pandiff( + 'test/old-metadata.md', + 'test/new-metadata.md', + { + files: true, + metadata: 'new', + to: 'markdown', + } + ); + const expected = fs.readFileSync('test/keep-new-metadata-diff.md', 'utf8'); + expect(output, expected); + }); + it('keep metadata from no document', async () => { + const output = await pandiff( + 'test/old-metadata.md', + 'test/new-metadata.md', + { + files: true, + metadata: 'none', + to: 'markdown', + } + ); + const expected = fs.readFileSync('test/keep-no-metadata-diff.md', 'utf8'); + expect(output, expected); + }); + it('keep metadata from old document without metadata', async () => { + const output = await pandiff('test/old.md', 'test/new.md', { + files: true, + metadata: 'old', + to: 'markdown', + }); + const expected = fs.readFileSync('test/diff.md', 'utf8'); + expect(output, expected); + }); + it('keep metadata from new document without metadata', async () => { + const output = await pandiff('test/old.md', 'test/new.md', { + files: true, + metadata: 'new', + to: 'markdown', + }); + const expected = fs.readFileSync('test/diff.md', 'utf8'); + expect(output, expected); + }); + it('keep metadata none document without metadata', async () => { + const output = await pandiff('test/old.md', 'test/new.md', { + files: true, + metadata: 'none', + to: 'markdown', + }); + const expected = fs.readFileSync('test/diff.md', 'utf8'); + expect(output, expected); + }); + it('keep no metadata if metadata is not specified', async () => { + const output = await pandiff( + 'test/old-metadata.md', + 'test/new-metadata.md', + { + files: true, + to: 'markdown', + } + ); + const expected = fs.readFileSync('test/keep-no-metadata-diff.md', 'utf8'); + expect(output, expected); + }); +}); diff --git a/src/index.ts b/src/index.ts index 3ae4d8f..8b336ce 100644 --- a/src/index.ts +++ b/src/index.ts @@ -274,7 +274,7 @@ async function extractMetadata(source: string) { if (lines[i].trim() === '---') break; } - return metadata.join('\n'); + return metadata.join('\n') + '\n'; } async function pandiff( @@ -285,9 +285,11 @@ async function pandiff( let metadata = ''; switch (opts.metadata) { case 'old': + opts.standalone = true; metadata = await extractMetadata(source1); break; case 'new': + opts.standalone = true; metadata = await extractMetadata(source2); break; default: @@ -441,7 +443,7 @@ async function postrender( opts: pandiff.Options = {}, metadata = '' ) { - if (!opts.output && !opts.to) return text; + if (!opts.output && !opts.to) return `${metadata}${text}`; if (!('highlight-style' in opts)) opts['highlight-style'] = 'kate'; let args = buildArgs( @@ -475,19 +477,21 @@ async function postrender( if (opts.standalone) args = args.concat(pandocOptionsHTML); } + if (opts.standalone) args = args.concat('-s'); + if (opts.output) { - await sh.pandoc(...args).end(`${metadata}\n${text}`); + await sh.pandoc(...args).end(`${metadata}${text}`); return null; } else { return sh .pandoc(...args) - .end(text) + .end(`${metadata}${text}`) .toString(); } } export = pandiff; -namespace pandiff { // eslint-disable-line + namespace pandiff { // eslint-disable-line export type File = string; export type Format = string; export type Path = string; diff --git a/test/keep-new-metadata-diff.md b/test/keep-new-metadata-diff.md new file mode 100644 index 0000000..2c766f0 --- /dev/null +++ b/test/keep-new-metadata-diff.md @@ -0,0 +1,15 @@ +--- +title: New Title +--- + +# {\~~Some~\>Differnt\~\~} Text + +Lorem {--ipsum --}dolor sit {~~amet,\~\>amet test,~~} consetetur +sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et +dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et +justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea +takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit +amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor +invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At +vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd +gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. diff --git a/test/keep-no-metadata-diff.md b/test/keep-no-metadata-diff.md new file mode 100644 index 0000000..01bd4aa --- /dev/null +++ b/test/keep-no-metadata-diff.md @@ -0,0 +1,11 @@ +# {\~~Some~\>Differnt\~\~} Text + +Lorem {--ipsum --}dolor sit {~~amet,\~\>amet test,~~} consetetur +sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et +dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et +justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea +takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit +amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor +invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At +vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd +gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. diff --git a/test/keep-old-metadata-diff.md b/test/keep-old-metadata-diff.md new file mode 100644 index 0000000..8b79450 --- /dev/null +++ b/test/keep-old-metadata-diff.md @@ -0,0 +1,15 @@ +--- +title: Old Title +--- + +# {\~~Some~\>Differnt\~\~} Text + +Lorem {--ipsum --}dolor sit {~~amet,\~\>amet test,~~} consetetur +sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et +dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et +justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea +takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit +amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor +invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At +vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd +gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. diff --git a/test/new-metadata.md b/test/new-metadata.md new file mode 100644 index 0000000..1ad7d0f --- /dev/null +++ b/test/new-metadata.md @@ -0,0 +1,6 @@ +--- +title: New Title +--- + +# Differnt Text +Lorem dolor sit amet test, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. diff --git a/test/old-metadata.md b/test/old-metadata.md new file mode 100644 index 0000000..6887d41 --- /dev/null +++ b/test/old-metadata.md @@ -0,0 +1,6 @@ +--- +title: Old Title +--- + +# Some Text +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.