Skip to content

Commit 34bc2b9

Browse files
committed
fix: rewrite file as markdown (not HTML), implement markdown-it-attrs and markdown-it-anchor
1 parent 2f37bf1 commit 34bc2b9

2 files changed

Lines changed: 45 additions & 59 deletions

File tree

index.js

Lines changed: 43 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ const { isIP } = require('net');
66
// const formatSpecifiers = require('format-specifiers');
77
const Redis = require('@ladjs/redis');
88
const _ = require('lodash');
9-
const autoLinkHeadings = require('remark-autolink-headings');
9+
// const autoLinkHeadings = require('remark-autolink-headings');
1010
const debug = require('debug')('mandarin');
11-
const emoji = require('remark-emoji');
11+
// const emoji = require('remark-emoji');
1212
const globby = require('globby');
1313
const isFQDN = require('is-fqdn');
1414
const isSANB = require('is-string-and-not-blank');
@@ -19,9 +19,10 @@ const pMapSeries = require('p-map-series');
1919
const pify = require('pify');
2020
const rehypeRaw = require('rehype-raw');
2121
const rehypeRewrite = require('rehype-rewrite');
22-
const rehypeStringify = require('rehype-stringify');
22+
// const rehypeStringify = require('rehype-stringify');
2323
const remarkParse = require('remark-parse');
2424
const remarkPresetGitHub = require('remark-preset-github');
25+
const remarkStringify = require('remark-stringify');
2526
const remarkRehype = require('remark-rehype');
2627
const revHash = require('rev-hash');
2728
const sharedConfig = require('@ladjs/shared-config');
@@ -31,6 +32,7 @@ const universalify = require('universalify');
3132
const vfile = require('to-vfile');
3233
const { v2 } = require('@google-cloud/translate');
3334
const { isEmail, isURL } = require('validator');
35+
const visit = require('unist-util-visit');
3436

3537
const isoCodes = Object.keys(languages.getAlpha2Codes());
3638
const writeFile = pify(fs.writeFile);
@@ -59,6 +61,22 @@ function parsePreAndPostWhitespace(str) {
5961
return [str.slice(0, index), value, str.slice(index + value.length)];
6062
}
6163

64+
// Custom plugin to add the {#id} syntax to the end of the heading text.
65+
const addCustomIdToHeadingText = () => (tree) => {
66+
visit(tree, 'heading', (node) => {
67+
// `remark-slug` has already added the ID to `node.properties.id`.
68+
const slug = node.data?.id; // Use optional chaining for safety.
69+
70+
if (slug) {
71+
// Append a new text node containing the custom ID syntax.
72+
node.children.push({
73+
type: 'text',
74+
value: ` {#${slug}}`
75+
});
76+
}
77+
});
78+
};
79+
6280
// GitHub alert patterns
6381
const GITHUB_ALERT_PATTERNS = [
6482
{ pattern: /^>\s*\[!NOTE\].*$/gm, type: 'NOTE' },
@@ -113,10 +131,6 @@ class Mandarin {
113131
}
114132
},
115133
//
116-
// New option to enable text-based translation
117-
//
118-
useTextTranslation: true,
119-
//
120134
// Concurrency limit for parallel translations
121135
//
122136
concurrency: 5
@@ -167,9 +181,9 @@ class Mandarin {
167181
}
168182

169183
// Improved method for text-based markdown translation using Promise.all and p-map
170-
async parseMarkdownFileText(filePath) {
171-
debug('parseMarkdownFileText', filePath);
172-
const content = await readFile(filePath, 'utf8');
184+
async parseMarkdownFileText(content, locale) {
185+
// debug('parseMarkdownFileText', filePath);
186+
// const content = await readFile(filePath, 'utf8');
173187

174188
// don't translate the main file.md file, only for other locales
175189
const locales = this.config.i18n.config.locales.filter(
@@ -517,17 +531,13 @@ class Mandarin {
517531
async parseMarkdownFile(filePath) {
518532
debug('parseMarkdownFile', filePath);
519533

520-
// Use text-based translation if enabled
521-
if (this.config.useTextTranslation) {
522-
return this.parseMarkdownFileText(filePath);
523-
}
524-
525534
// Original HTML-based implementation
526535
const markdown = await vfile.read(filePath);
527536
// don't translate the main file.md file, only for other locales
528537
const locales = this.config.i18n.config.locales.filter(
529538
(locale) => locale !== this.config.i18n.config.defaultLocale
530539
);
540+
531541
const files = await Promise.all(
532542
locales.map((locale) => {
533543
return new Promise((resolve, reject) => {
@@ -536,51 +546,27 @@ class Mandarin {
536546
.use(remarkPresetGitHub)
537547
.use(remarkParse)
538548
.use(slug)
549+
/*
539550
.use(autoLinkHeadings, {
540-
behavior: 'prepend',
551+
behavior: 'prepend', // Use 'prepend' or 'append', but NOT 'wrap'.
552+
// The content for the new, separate link.
541553
content: {
542-
type: 'element',
543-
tagName: 'i',
544-
properties: {
545-
className: ['fa', 'fa-link', 'mr-2', 'text-dark']
546-
},
547-
children: []
554+
type: 'text',
555+
value: '🔗', // Using an emoji for the link content.
556+
},
557+
// Link properties can be added if needed, e.g., for CSS classes.
558+
properties: {
559+
ariaHidden: 'true',
560+
class: 'anchor'
548561
}
549562
})
550-
.use(emoji)
551-
.use(remarkRehype, { allowDangerousHtml: true })
552-
.use(rehypeRaw)
553-
.data('settings', { fragment: true, emitParseErrors: true })
554-
.use(rehypeRewrite, (node, index, parent) => {
555-
if (
556-
locale !== 'en' &&
557-
node.type === 'text' &&
558-
parent.tagName !== 'code' &&
559-
isSANB(node.value) &&
560-
node.value !== node.value.toUpperCase()
561-
) {
562-
// if the `parent.tagName` is `code`
563-
// or if the `node.value` is empty string (and not just \n either)
564-
// or if the `node.value` when converted to uppercase is the same (e.g. abbreviation)
565-
// then do not translate the value using i18n
566-
// otherwise translate the value and set the new node value
567-
//
568-
// NOTE: we must strip the preceeding and succeeding whitespace and line breaks
569-
// and then add them back after the string is successfully translated
570-
//
571-
const [pre, phrase, post] = parsePreAndPostWhitespace(
572-
node.value
573-
);
574-
node.value =
575-
pre +
576-
this.config.i18n.api.t({
577-
phrase,
578-
locale
579-
}) +
580-
post;
581-
}
563+
*/
564+
.use(addCustomIdToHeadingText)
565+
.use(remarkStringify, {
566+
// Important: This option prevents the processor from escaping the `{` and `}`
567+
// characters in our custom ID.
568+
fences: true
582569
})
583-
.use(rehypeStringify)
584570
.process(markdown, (err, file) => {
585571
if (err) return reject(err);
586572
resolve({ locale, content: String(file) });
@@ -594,8 +580,9 @@ class Mandarin {
594580
filePath,
595581
file.locale
596582
);
583+
const translatedContent = await this.translateMarkdownContent(file.content, file.locale);
597584
debug('writing file', localizedFilePath);
598-
await writeFile(localizedFilePath, file.content);
585+
await writeFile(localizedFilePath, translatedContent);
599586
})
600587
);
601588
}

package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,15 @@
3131
"pify": "5",
3232
"rehype-raw": "5",
3333
"rehype-rewrite": "1",
34-
"rehype-stringify": "8",
35-
"remark-autolink-headings": "6",
36-
"remark-emoji": "2",
3734
"remark-parse": "9",
3835
"remark-preset-github": "^4.0.4",
3936
"remark-rehype": "8",
4037
"remark-slug": "6",
38+
"remark-stringify": "^9.0.1",
4139
"rev-hash": "3",
4240
"to-vfile": "6",
4341
"unified": "9",
42+
"unist-util-visit": "^2.0.3",
4443
"universalify": "^2.0.0",
4544
"validator": "^13.9.0"
4645
},

0 commit comments

Comments
 (0)