Last active
July 3, 2022 23:04
-
-
Save exceedsystem/0d6095ea400eb4ab2bf6c3d3feefe1c0 to your computer and use it in GitHub Desktop.
An example of 'Markdown formatter' macro for VSCodeMacros extension
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// [VSCode Macros] extension | |
// https://marketplace.visualstudio.com/items?itemName=EXCEEDSYSTEM.vscode-macros | |
// License:MIT | |
const vscode = require('vscode'); | |
const remark = require('remark'); // Requires version 13 or above | |
const remarkParse = require('remark-parse'); | |
const remarkStringify = require('remark-stringify'); | |
const remarkGFM = require('remark-gfm'); | |
const remarkFrontmatter = require('remark-frontmatter'); // Requires version 3 or above | |
module.exports.macroCommands = { | |
FormatMarkdown: { | |
no: 1, | |
func: formatMD, | |
}, | |
}; | |
function formatMD() { | |
const editor = vscode.window.activeTextEditor; | |
if (!editor) { | |
vscode.window.showWarningMessage('Editor not found.'); | |
return; | |
} | |
const document = editor.document; | |
if (!document) { | |
vscode.window.showWarningMessage('Document not found.'); | |
return; | |
} | |
if (document.languageId !== 'markdown') { | |
vscode.window.showWarningMessage(`This document type '${document.languageId}' is not supported.`); | |
return; | |
} | |
// Get east asian ambiguous characters | |
const eastAsianAmbiguous = Array.from('μ').map(s => s.codePointAt(0)); | |
// Markdown formatting options(https://github.com/syntax-tree/mdast-util-to-markdown#formatting-options) | |
const remarksOptions = { | |
bullet: '-', | |
listItemIndent: 'one', | |
rule: '-' | |
}; | |
const srcMarkdown = document.getText(); | |
// Convert markdown text to the syntax tree | |
const mdNode = remark() | |
.use(remarkGFM) | |
.use(remarkParse) | |
.use(remarkFrontmatter) | |
.parse(srcMarkdown); | |
// Convert the syntax tree to markdown text | |
const dstMarkdown = remark() | |
.use(remarkGFM, { | |
// Calculate the number of characters in a cell | |
stringLength: (s) => { | |
let len = 0; | |
Array.from(s).forEach((elem) => { | |
let cpv; | |
const codePointValue = (cpv = elem.codePointAt(0)) !== undefined ? cpv : 0; | |
if (codePointValue <= 255 || (codePointValue >= 0xff61 && codePointValue <= 0xff9f || eastAsianAmbiguous.includes(codePointValue))) | |
++len; | |
else | |
// Double width | |
len += 2; | |
}); | |
return len; | |
}, | |
}) | |
.use(remarkStringify, remarksOptions) | |
.use(remarkFrontmatter) | |
.stringify(mdNode); | |
if (srcMarkdown === dstMarkdown) { | |
vscode.window.showInformationMessage('Document is already formatted.'); | |
return; | |
} | |
editor.edit((editBuilder) => { | |
// Replace with formatted markdown | |
const firstLine = document.lineAt(0); | |
const lastLine = document.lineAt(document.lineCount - 1); | |
editBuilder.replace(new vscode.Range(firstLine.range.start, lastLine.range.end), dstMarkdown); | |
vscode.window.showInformationMessage('Format completed.'); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment