From a46f76092759ae7c3a87bc466b9c15e15eb69349 Mon Sep 17 00:00:00 2001 From: eagletrhost Date: Tue, 14 Oct 2025 23:34:21 +1100 Subject: [PATCH 1/5] feat: replace
tags in migrate --- lib/migrate.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/migrate.ts b/lib/migrate.ts index 70aa90e83..492f7a014 100644 --- a/lib/migrate.ts +++ b/lib/migrate.ts @@ -14,6 +14,7 @@ const migrate = (doc: string, { rdmd }): string => { // 'a' to 'a' as a means of escaping it. I think this helps with // parsing weird cases. .replaceAll(/a/g, 'a') + .replaceAll(//g, '
') ); }; From 01f9490c3558446d70ff078a70784697ae0c57cc Mon Sep 17 00:00:00 2001 From: eagletrhost Date: Wed, 15 Oct 2025 16:56:41 +1100 Subject: [PATCH 2/5] feat: add regex for replacing <<>> variables with user. --- __tests__/migration/variables.test.ts | 33 +++++++++++++++++++++++++++ lib/migrate.ts | 1 + 2 files changed, 34 insertions(+) create mode 100644 __tests__/migration/variables.test.ts diff --git a/__tests__/migration/variables.test.ts b/__tests__/migration/variables.test.ts new file mode 100644 index 000000000..89a6e998e --- /dev/null +++ b/__tests__/migration/variables.test.ts @@ -0,0 +1,33 @@ +import { migrate } from '../helpers'; + +describe('migrating variables', () => { + it('converts <> to {user.something}', () => { + const md = 'Hello <>, your <> is important.'; + + const mdx = migrate(md); + expect(mdx).toMatchInlineSnapshot(` + "Hello {user.name}, your {user.role} is important. + " + `); + }); + + it('handles variables with underscores and numbers', () => { + const md = 'User <> has <> access.'; + + const mdx = migrate(md); + expect(mdx).toMatchInlineSnapshot(` + "User {user.user_id} has {user.api_key_123} access. + " + `); + }); + + it('does not affect glossary items', () => { + const md = '<> and <>'; + + const mdx = migrate(md); + expect(mdx).toMatchInlineSnapshot(` + "{user.name} and Listings + " + `); + }); +}); diff --git a/lib/migrate.ts b/lib/migrate.ts index 492f7a014..57c549068 100644 --- a/lib/migrate.ts +++ b/lib/migrate.ts @@ -15,6 +15,7 @@ const migrate = (doc: string, { rdmd }): string => { // parsing weird cases. .replaceAll(/a/g, 'a') .replaceAll(//g, '
') + .replaceAll(/<<([^>]+)>>/g, '{user.$1}') ); }; From ea8fea4c5a9c2b94f5565b4a1619ff5a558ed108 Mon Sep 17 00:00:00 2001 From: eagletrhost Date: Fri, 17 Oct 2025 00:13:53 +1100 Subject: [PATCH 3/5] fix: remove variable regex --- __tests__/migration/variables.test.ts | 33 --------------------------- lib/migrate.ts | 2 +- 2 files changed, 1 insertion(+), 34 deletions(-) delete mode 100644 __tests__/migration/variables.test.ts diff --git a/__tests__/migration/variables.test.ts b/__tests__/migration/variables.test.ts deleted file mode 100644 index 89a6e998e..000000000 --- a/__tests__/migration/variables.test.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { migrate } from '../helpers'; - -describe('migrating variables', () => { - it('converts <> to {user.something}', () => { - const md = 'Hello <>, your <> is important.'; - - const mdx = migrate(md); - expect(mdx).toMatchInlineSnapshot(` - "Hello {user.name}, your {user.role} is important. - " - `); - }); - - it('handles variables with underscores and numbers', () => { - const md = 'User <> has <> access.'; - - const mdx = migrate(md); - expect(mdx).toMatchInlineSnapshot(` - "User {user.user_id} has {user.api_key_123} access. - " - `); - }); - - it('does not affect glossary items', () => { - const md = '<> and <>'; - - const mdx = migrate(md); - expect(mdx).toMatchInlineSnapshot(` - "{user.name} and Listings - " - `); - }); -}); diff --git a/lib/migrate.ts b/lib/migrate.ts index 57c549068..8863ebbfa 100644 --- a/lib/migrate.ts +++ b/lib/migrate.ts @@ -14,8 +14,8 @@ const migrate = (doc: string, { rdmd }): string => { // 'a' to 'a' as a means of escaping it. I think this helps with // parsing weird cases. .replaceAll(/a/g, 'a') + // A common issue is that
tags are not properly closed .replaceAll(//g, '
') - .replaceAll(/<<([^>]+)>>/g, '{user.$1}') ); }; From 5a7ae0362225fb1ecf18c2675b3240ddcead8193 Mon Sep 17 00:00:00 2001 From: eagletrhost Date: Fri, 17 Oct 2025 10:48:40 +1100 Subject: [PATCH 4/5] feat: move
regex to tree traversal & add test --- __tests__/migration/html-tags.test.ts | 47 ++++++++++++++++++++++++ lib/migrate.ts | 5 +-- processor/transform/migrate-html-tags.ts | 14 +++++++ 3 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 __tests__/migration/html-tags.test.ts create mode 100644 processor/transform/migrate-html-tags.ts diff --git a/__tests__/migration/html-tags.test.ts b/__tests__/migration/html-tags.test.ts new file mode 100644 index 000000000..a82c65476 --- /dev/null +++ b/__tests__/migration/html-tags.test.ts @@ -0,0 +1,47 @@ +import { migrate } from '../helpers'; + +describe('migrating html tags', () => { + describe('br tags', () => { + it('converts unclosed br tags to self-closing', () => { + const md = `This is a line with a break
and another line. +Multiple breaks

in sequence. +Already closed
should remain unchanged.`; + + const mdx = migrate(md); + expect(mdx).toMatchInlineSnapshot(` + "This is a line with a break
and another line.\\ + Multiple breaks

in sequence.\\ + Already closed
should remain unchanged. + " + `); + }); + + it('handles br tags with attributes', () => { + const md = 'Line with styled break
and more text.'; + + const mdx = migrate(md); + expect(mdx).toMatchInlineSnapshot(` + "Line with styled break
and more text. + " + `); + }); + + it('does not change br tags inside code blocks', () => { + const md = `Not a \`
\` tag. + +\`\`\` +Also not a \`
\` tag. +\`\`\``; + + const mdx = migrate(md); + expect(mdx).toMatchInlineSnapshot(` + "Not a \`
\` tag. + + \`\`\` + Also not a \`
\` tag. + \`\`\` + " + `); + }); + }); +}); diff --git a/lib/migrate.ts b/lib/migrate.ts index 8863ebbfa..6d4e55b36 100644 --- a/lib/migrate.ts +++ b/lib/migrate.ts @@ -1,4 +1,5 @@ import migrateCallouts from '../processor/transform/migrate-callouts'; +import migrateHtmlTags from '../processor/transform/migrate-html-tags'; import migrateLinkReferences from '../processor/transform/migrate-link-references'; import mdastV6 from './mdastV6'; @@ -8,14 +9,12 @@ const migrate = (doc: string, { rdmd }): string => { const ast = mdastV6(doc, { rdmd }); return ( - mdx(ast, { remarkTransformers: [migrateCallouts, migrateLinkReferences], file: doc }) + mdx(ast, { remarkTransformers: [migrateCallouts, migrateLinkReferences, migrateHtmlTags], file: doc }) .replaceAll(/ /g, ' ') // @note: I'm not sure what's happening, but I think mdx is converting an // 'a' to 'a' as a means of escaping it. I think this helps with // parsing weird cases. .replaceAll(/a/g, 'a') - // A common issue is that
tags are not properly closed - .replaceAll(//g, '
') ); }; diff --git a/processor/transform/migrate-html-tags.ts b/processor/transform/migrate-html-tags.ts new file mode 100644 index 000000000..a859c4911 --- /dev/null +++ b/processor/transform/migrate-html-tags.ts @@ -0,0 +1,14 @@ +import type { Root } from 'mdast'; + +import { visit } from 'unist-util-visit'; + +// Add more visits to migrate other HTML tags here +const migrateHtmlTags = () => (tree: Root) => { + // A common issue is that
tags are not properly closed + // HTML tags like
are parsed as 'html' nodes + visit(tree, 'html', htmlNode => { + htmlNode.value = htmlNode.value.replaceAll(/)([^>]*?)>/g, ''); + }); +}; + +export default migrateHtmlTags; From 40c12a7575588e088a78de55ca7129ed28ee253e Mon Sep 17 00:00:00 2001 From: eagletrhost Date: Fri, 17 Oct 2025 10:49:09 +1100 Subject: [PATCH 5/5] remove comment --- processor/transform/migrate-html-tags.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/processor/transform/migrate-html-tags.ts b/processor/transform/migrate-html-tags.ts index a859c4911..320e3c172 100644 --- a/processor/transform/migrate-html-tags.ts +++ b/processor/transform/migrate-html-tags.ts @@ -5,7 +5,6 @@ import { visit } from 'unist-util-visit'; // Add more visits to migrate other HTML tags here const migrateHtmlTags = () => (tree: Root) => { // A common issue is that
tags are not properly closed - // HTML tags like
are parsed as 'html' nodes visit(tree, 'html', htmlNode => { htmlNode.value = htmlNode.value.replaceAll(/)([^>]*?)>/g, ''); });