-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Add Markdown Link Converter Script #8650
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 26_1
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| let fs = require('fs'); | ||
| let path = require('path'); | ||
|
|
||
| const specifiedPath = process.argv[2]; | ||
| const linkRegex = /<a\b(?=[^>]*\btarget=["']_blank["'])[^>]*\bhref=["']([^"']*)["'][^>]*>([\s\S]*?)<\/a>/gi; | ||
|
|
||
| function isInsideTableCell(content, offset) { | ||
| const before = content.slice(0, offset).toLowerCase(); | ||
|
Comment on lines
+1
to
+8
|
||
| const after = content.slice(offset).toLowerCase(); | ||
|
|
||
| return before.lastIndexOf('<td') > before.lastIndexOf('</td>') && after.includes('</td>'); | ||
| } | ||
|
|
||
| function escapeForRegex(value) { | ||
| return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); | ||
| } | ||
|
|
||
| function isInsideCodeSnippet(content, offset) { | ||
| const lineStart = content.lastIndexOf('\n', offset - 1) + 1; | ||
| const lineEndIndex = content.indexOf('\n', offset); | ||
| const lineEnd = lineEndIndex === -1 ? content.length : lineEndIndex; | ||
| const line = content.slice(lineStart, lineEnd); | ||
| const indentMatch = line.match(/^[\t ]+(?=<a\b)/i); | ||
|
|
||
| if (!indentMatch) { | ||
| return false; | ||
| } | ||
|
|
||
| const indent = indentMatch[0]; | ||
| const commentRegex = new RegExp(`^${escapeForRegex(indent)}(?:<!--\s*tab:\s*index\.html\s*-->|<!--\s*HTML\s*-->)\s*$`, 'i'); | ||
|
|
||
| const linesAbove = content.slice(0, lineStart).split(/\r?\n/); | ||
|
|
||
| for (let i = linesAbove.length - 1; i >= 0; i -= 1) { | ||
| const currentLine = linesAbove[i]; | ||
|
|
||
| if (!currentLine.trim()) { | ||
| continue; | ||
| } | ||
|
|
||
| if (commentRegex.test(currentLine)) { | ||
| return true; | ||
| } | ||
|
|
||
| if (!currentLine.startsWith(indent)) { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| function getFilePaths(targetPath) { | ||
| const stats = fs.statSync(targetPath); | ||
|
|
||
| if (stats.isFile()) { | ||
| return [targetPath]; | ||
| } | ||
|
|
||
| if (!stats.isDirectory()) { | ||
| return []; | ||
| } | ||
|
|
||
| return fs.readdirSync(targetPath, { withFileTypes: true }).flatMap((entry) => { | ||
| const entryPath = path.join(targetPath, entry.name); | ||
|
|
||
| if (entry.isDirectory()) { | ||
| return getFilePaths(entryPath); | ||
| } | ||
|
|
||
| return entry.isFile() ? [entryPath] : []; | ||
| }); | ||
|
Comment on lines
+52
to
+71
|
||
| } | ||
|
|
||
| function convertFile(filePath) { | ||
| const content = fs.readFileSync(filePath, 'utf-8'); | ||
| const updatedContent = content.replace(linkRegex, (match, href, innerHtml, offset) => { | ||
| if (isInsideTableCell(content, offset) || isInsideCodeSnippet(content, offset)) { | ||
| return match; | ||
| } | ||
|
|
||
| return `[${innerHtml}](${href})`; | ||
| }); | ||
|
Comment on lines
+74
to
+82
|
||
|
|
||
| if (updatedContent !== content) { | ||
| fs.writeFileSync(filePath, updatedContent, 'utf-8'); | ||
| return true; | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| if (!specifiedPath) { | ||
| console.error('Specify a file or directory path.'); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| try { | ||
| const filePaths = getFilePaths(specifiedPath); | ||
| let updatedFilesCount = 0; | ||
|
|
||
| filePaths.forEach((filePath) => { | ||
| if (convertFile(filePath)) { | ||
| updatedFilesCount += 1; | ||
| } | ||
| }); | ||
|
|
||
| console.log(`Processed ${filePaths.length} file(s). Updated ${updatedFilesCount} file(s).`); | ||
| } catch (error) { | ||
| console.error(error.message || error); | ||
| process.exit(1); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new npm script runs a
.jsfile viats-node. By default,ts-nodedoes not execute plain JavaScript unless it is configured withallowJs, so this script can fail in a clean environment. Either run it withnodeor rename the file to.tsand keepts-nodeconsistent with the othertools/*.tsscripts.