Markdown 计算器






3.89/5 (6投票s)
这只是一个有趣的 Visual Studio Code 扩展,但是……如果有人试图认真使用它,会发生什么呢?
引言如果你想创造一些完全无用或荒谬的东西,那就非常认真地去做。只有这样你才有成功的机会。
Content
动机
用法
洞见
设置
控制台
带内联代码的控制台
如何尝试?
实现
代码块的执行
内联代码的执行
计算和控制台 API
下一步?
结论
动机
如今,我们可以用手机拍照,用冰箱上网,和我们的吸尘器说话。话虽如此,我们能用什么作为计算器呢?可能,首先,最自然的东西是某种文本编辑器。
还有别的吗?是的,另一个合适的工具是浏览器。但现在,让我们看看我们能用文本编辑器做什么。
此时,或许是时候说一下,使用电脑的人通常没有有用的东西来做计算。的确,我们如何称呼一个普通的 Windows 或 Linux 应用程序“计算器”为计算器呢?显然,这类应用程序的主要目的是展示电脑出现前的生活有多么困难:用户只有一个微小的低对比度黑白屏幕上的几个数字,不得不按按钮,而无法真正看到正在发生什么。为了让电脑模拟更加不方便,用户被迫用鼠标点击那些按钮。
因此,我向这个非常方便、功能丰富的文本编辑器、开源跨平台 Visual Studio Code 介绍了我的扩展。这个基于 Markdown 的扩展更接近我们从小学就知道的自然计算方式:拿一张纸或一个笔记本,逐行写下计算的步骤。当我们写下我们所做的事情时,我们需要在正常文本行之间写下这些数字和算术运算符:给定什么,我们做什么步骤,以及最终结果是什么。
让我们看看我们该怎么做。
用法
洞见
假设,在这个阳光明媚的春日,你正在写一封情书,并且想在信的末尾送上一百万个吻。当然,你需要一个格式良好且易于维护的文档,所以你使用 Visual Studio Code 和 Markdown。
作为一名高级工程师,你自然不应该记住常数,也不应该手动做任何事情。你会强烈倾向于写诸如 10 ** 6
kisses 之类的内容。或者,如果你更浪漫,你可能想送 1 << 20
个吻,也就是说,一个兆吻,或者更准确地说,一个Mebikiss。
然而,假设你的心上人不太懂电脑语言,甚至不习惯二进制移位。在这种情况下,你想写 10 ** 6
,但在输出文档中将其渲染为老式的一百万个吻。
你可以通过使用 VSCode 的 Markdown Calculator 扩展来实现,输入 return 10 ** 6
kisses 来代替 1000000
。
在你关系更成熟的阶段,你可能需要检查你的开销并提供一些购买证明。你可以在 VSCode 中使用带有“run”关键字的代码块来做到这一点,写在第一行。
~~~ run
const eggs = 3.49, sourCream = 2.49, milk = 4.99
const gel = 19.99, vitamines = 17.99
const taxable = gel + vitamines
const tax = taxable * 6.25 / 100
const total = eggs + sourCream + milk + taxable + tax
console.log(`Total: $${Math.round(total * 100) / 100}`);
~~~
该扩展会将其渲染为计算结果,显示为通过 console.log
创建的控制台内容。在这种情况下,它将是 $51.32
。但是,也可以使用 return
;它将显示在最后。
你知道,缺少 return
语句等同于 return undefined
,而对象 undefined
是该扩展唯一渲染为空字符串的对象,与 null
(渲染为“null”)相反。
在所有情况下,所有异常都会被捕获,并且异常消息会使用特殊的 CSS 样式进行渲染。
你只需使用 VSCode 预览就可以做到所有这些。对于更严肃的工作,你可能想将文档转换为 HTML;你可以使用在文章用 Visual Studio Code 编写文章的工具链中描述的“可扩展 Markdown”扩展来完成。它还暴露或提供了许多有用的 Markdown 语法扩展,以及添加更多可用或新扩展的可能性。
设置
已安装的扩展可以在用户或工作区设置中启用或禁用。此外,代码块执行和内联代码执行这两个功能可以独立启用或禁用。此外,“run”关键字是可配置的,以及不同 console
函数输出的不同 CSS 类。
- Markdown > Calculator > Enable: 启用所有扩展功能,包括语法装饰器
- Markdown > Calculator > Fenced Code Block > Enable: 启用 Markdown Calculator 对代码块行为的修改
- Markdown > Calculator > Fenced Code Block > Enable: 启用 Markdown Calculator 对代码块行为的修改
- Markdown > Calculator > Inline Code > Enable: 启用 Markdown Calculator 对内联代码行为的修改
- Markdown > Calculator > Execution Indicator: 用于指示代码执行而非常规渲染的标记;默认值:
"run"
- Markdown > Calculator > Keyword Decorator > Color: 用于突出显示执行指示器的背景颜色
- Markdown > Calculator > Keyword Decorator > Hover Text: 显示执行指示器关键字用途的悬停文本
- Markdown > Calculator > CSS Class > Exception: 用于异常文本渲染的 CSS 类名
- Markdown > Calculator > CSS Class > Return: 用于计算返回值的 CSS 类名
- Markdown > Calculator > CSS Class > Console > Assert: 用于
console.assert
的 CSS 类名 - Markdown > Calculator > CSS Class > Console > Debug: 用于
console.debug
的 CSS 类名 - Markdown > Calculator > CSS Class > Console > Dir: 用于
console.dir
的 CSS 类名 - Markdown > Calculator > CSS Class > Console > Error: 用于
console.error
的 CSS 类名 - Markdown > Calculator > CSS Class > Console > Info: 用于
console.info
的 CSS 类名 - Markdown > Calculator > CSS Class > Console > Log: 用于
console.log
的 CSS 类名 - Markdown > Calculator > CSS Class > Console > Warm: 用于
console.warn
的 CSS 类名
控制台
“控制台”到底是什么?首先,它是一个带有某些 API 的 JavaScript 对象。通常,我们使用某些 JavaScript API(再次强调,强烈推荐 Visual Studio Code),它有一个供开发者使用的控制台。但我们需要一些不同的东西。
使用 Visual Studio Code,编写文档的标准方法是使用 Markdown,而通常的工作流程是左边是 markdown 代码,右边是预览窗格,我们可以立即看到渲染的文档——参见顶部的图片。这就是我们需要获得计算结果的地方。
此外,Markdown 可以被渲染并保存为 HTML 文件;它应该以相同的方式渲染内容。可以使用扩展 Extensible Markdown 来完成。本文就是这样编写的。
使用 console.log
函数的示例上面已经展示。
带内联代码的控制台
乍一看,似乎不可能为内联代码片段使用控制台输出,因为内容以关键字 return 开头,后跟单个表达式。这是不正确的;可以使用控制台。这完全取决于那个单一的表达式是什么。例如,这个表达式就可以达到目的
To use the console,
`return {
a: console.log("return an undefined object property"),
nothing: undefined}.
nothing`.
它将渲染:To use the console, return an undefined object property
。如果去掉 .nothing
,它也会在最后渲染 [object Object]
。
这样做是因为该扩展会为所有对象渲染返回值,包括 null
,但不会渲染 undefined
。我特意这样设计,作为一个用于静默返回值的工具。这对于代码块尤其有用,因为缺少 return
的函数实际上返回 undefined
。
如何尝试?
您无需安装扩展即可进行尝试。您只需要一个可用的 Visual Studio Code。
打开 Visual Studio Code,并将工作目录设置为当前页面上可下载并已解压的源代码根目录。它将是包含主扩展文件“package.json”的目录。
或者,您可以使用提供的工作区文件“MarkdownCalculator.code-workspace”启动 Visual Studio Code。
它将加载扩展项目。此项目附带“launch.json”,用于启动另一个加载了扩展的 Visual Studio Code 进程。要启动它,请按 F5。
尽情享用!
实现
代码块的执行
该应用程序使用了最简单的 markdown-it 技术之一:修改 markdown-it 渲染器在存在关键字时的行为,保存之前的规则函数,并在所有其他情况下调用它。
const previousFenceRenderer = md.renderer.rules.fence;
md.renderer.rules.fence = (tokens, index, ruleOptions, object, renderer) => {
if (settings.enable && settings.fencedCodeBlock.enable &&
tokens[index].info.trim() == settings.executionIndicator)
return `${renderFunction(tokens[index].content)}`;
else
return renderDefault(
tokens, index, ruleOptions, object,
renderer, previousFenceRenderer);
};
内联代码的执行
内联代码的情况非常相似。关键字不同:它是 return
,这也是一个 JavaScript 关键字,因此无法通过设置进行修改。此外,对 renderFunction
的调用中的第二个参数表明需要对内联表达式进行求值。
const previousInlineCodeRenderer = md.renderer.rules.code_inline;
md.renderer.rules.code_inline =
(tokens, index, ruleOptions, object, renderer) => {
let expressionString = tokens[index].content.trim();
if (settings.enable && settings.inlineCode.enable
&& expressionString.startsWith(`${inlineKeyword} `))
return `${renderFunction(expressionString, true)}`;
else
return renderDefault(
tokens, index, ruleOptions, object,
renderer, previousInlineCodeRenderer);
};
计算和控制台 API
计算基于 Function
对象。
这是一个相当微妙的问题,主要是因为 VSCode 环境受到保护,可以防止在代码块或内联代码中放置恶意或粗心的代码。这在另一篇文章JavaScript Playground中有详细描述。
一个有趣的功能是 console
对象的模拟。在执行过程中收集传递给 console
函数的对象,然后使用从设置中获得的 CSS 名称和 style
属性将它们渲染为 HTML。
const consoleApi = {
lines: [],
initialize: function() {
const handleArguments = (elements, cssClass) => {
this.lines.push({elements: elements, cssClass: cssClass});
}; //
const console = {
assert: (assertion, ...args) => {
if (!assertion)
handleArguments(args, settings.cssClass.console.assert);
},
debug: (...args) => {
handleArguments(args, settings.cssClass.console.debug);
},
dir: (...args) => {
handleArguments(args, settings.cssClass.console.dir);
},
error: (...args) => {
handleArguments(args, settings.cssClass.console.error)
},
info: (...args) => {
handleArguments(args, settings.cssClass.console.info);
},
log: (...args) => {
handleArguments(args, settings.cssClass.console.log);
},
warn: (...args) => {
handleArguments(args, settings.cssClass.console.warn);
},
};
return setReadonly(console);
},
render: function() {
let result = "";
if (this.lines.length < 1) return result;
for (let line of this.lines) {
let renderedLine = "";
for (let element of line.elements)
renderedLine += `${element} `;
renderedLine = renderedLine.trim();
result +=
`<p class="${line.cssClass}">${renderedLine}</p>`;
}; //loop
return result;
},
clear: function() {
this.lines.splice(0);
},
};
const console = consoleApi.initialize();
只实现了一部分 console
函数。另请参阅console
对象文档。
下一步是什么?
我们提供了一种自然的计算方法,类似于纸上进行的常规计算。接下来是什么?当然,这将是我们每个人在脑海中进行的计算,即心算。
这里是合适算法的草图
- 应用某种脑读技术,
- 将读取到的思维模式解析为命令,
- 将命令翻译成 JavaScript 文本,
- 将文本传递给构造函数
Function
, - 调用该函数,
- 如果它抛出异常,则捕获它,并以电击的形式发出负面刺激。
结论
思维惯性是件坏事。
我们不应模仿人们过去使用的过时和有限的设备,而应寻找执行简单事情的理性自然方式。今天这是正在编辑的文档中的计算,明天将支持脑读。无论如何,这都将值得一篇单独的文章——只需订阅 Code Project 时事通讯。