regex 将减价链接从内嵌转换为引用

mwyxok5s  于 2022-11-18  发布在  其他
关注(0)|答案(4)|浏览(202)

我 有 一 个 使用 Github's markdown 格式化 的 更改 日志 文件 。
最初 我 使用 * 内联 * 链接 的 每 一 个 链接 , 我 需要 添加 , 即 :

This is some [example](http://www.stackoverflow.com) line of text.

中 的 每 一 个
随着 时间 的 推移 , 随着 文件 大小 的 增长 , 它 变得 有点 混乱 , 主要 是 由于 这种 插入 链接 的 方式 。
我 想 将 所有 链接 从 * inline * 转换 为 * reference * ( 请 参阅 每个 链接 的 描述 ) , 也 就是 将 上面 的 行 转换 为 :

This is some [example][1] line of text.

[1]: http://www.stackoverflow.com

格式
因为 这个 文件 很 大 , 而且 包含 很多 * inline * 链接 , 我 想 知道 是否 有 一些 自动 化 的 方法 来 完成 这个 任务 。 我 使用 Sublime Text 3 来 编辑 , 但是 我 找 不到 一 个 适合 这个 任务 的 包 。 也许 是 一些 聪明 的 正则 表达式 ?

2izufjch

2izufjch1#

这是一个伟大的要求!
我刚刚创建了一个新的Node.js程序(我知道它不是一个GUI,但似乎更多的人希望它的功能)来在GitHub上完成这一任务。
下面也是代码:

// node main.js test.md result.md

var fs = require('fs')
fs.readFile(process.argv[2], 'utf8', function (err, markdown) {
    if (err) {
        return console.log(err);
    }
    var counter = 1;
    var matches = {};
    var matcher = /\[.*?\]\((.*?)\)/g;
    while (match = matcher.exec(markdown)) {
        if (!matches[match[1]]) matches[match[1]] = counter++;
    }
    console.log(matches);
    Object.keys(matches).forEach(function(url) {
        var r = new RegExp("(\\[.*?\\])\\(" + url + "\\)", "g");
        markdown = markdown.replace(r, "$1[" + matches[url] + "]");
        markdown += "\n[" + matches[url] + "]: " + url;
    });

    fs.writeFile(process.argv[3], markdown, 'utf8', function (err) {
        if (err) return console.log(err);
    });

});
ep6jt1vc

ep6jt1vc2#

将其保存为Packages文件夹中的mdrelink.py,然后可以使用

view.run_command('mdrelink');

从命令控制台中。
我 * 认为 * 我得到了正确的顺序-反转是必要的,因为否则它会弄乱已经缓存的下一个项目的索引。它也应该自动跳过已经使用的链接编号。我的第一个Python * 和 * 我的第一个Sublime插件,所以请对我温柔一点。

import sublime, sublime_plugin

class mdrelinkCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        oldlinks = []
        self.view.find_all("^\s*(\[\d+\]):", sublime.IGNORECASE, "\\1", oldlinks)
        newlinkpos = self.view.find_all("\[.+?\](\(.+?\))")
        orgtext = []
        self.view.find_all("(\[.+?\])\(.+?\)", sublime.IGNORECASE, "\\1", orgtext)
        orglink = []
        self.view.find_all("\[.+?\]\((.+?)\)", sublime.IGNORECASE, "\\1", orglink)
        orglink.reverse()
        self.view.insert(edit, self.view.size(), '\n\n')
        counter = 1
        newnumbers = []
        for r in newlinkpos:
            while '['+str(counter)+']' in oldlinks:
                 counter += 1
            oldlinks.append('['+str(counter)+']')
            line = '[' + str(counter)+']: '+ orglink.pop() + '\n'
            newnumbers.append('  ['+str(counter)+']')
            self.view.insert(edit, self.view.size(), line)
        for r in reversed(newlinkpos):
            self.view.replace(edit, r, orgtext.pop()+newnumbers.pop())
vcudknz3

vcudknz33#

感谢Google,我偶然发现了这个问题。也许这可以帮助其他人:
我的答案不是Sublime特定的,但是如果您已经在使用JavaScript(Node),我会使用Markdown解析器和CST转换器,比如remark
例如,要将README.md中得所有内联链接转换为numerically-ascending reference-style links,可以在项目得根目录下运行以下命令:

npm install --save-dev remark-cli remark-renumber-references
npx remark --no-stdout --output --use renumber-references README.md

或者,如果您需要reference-style links derived from the source uri

npm install --save-dev remark-cli remark-defsplit
npx remark --no-stdout --output --use defsplit README.md

希望这些信息能帮助像我这样的人不要浪费一整天的时间来破解一些基于正则表达式的非常不可靠的解决方案:)

kulphzqa

kulphzqa4#

扩展@bjfletcher的答案,下面是考虑任何现有引用链接的代码。
链接到GitHub gist

// node filename.js ReadMe.md RefLinks.md

import * as fs from 'fs'
fs.readFile(process.argv[2], 'utf8', function (err, mainMarkdown) {
    if (err) {
        return console.log(err);
    }
    let newMarkdown = existingRefLinks(mainMarkdown);

    var counter = 1;
    var matches = {};
    var matcher = /\[.*?\]\((.*?)\)/g
    let match;
    while (match = matcher.exec(newMarkdown)) {
        if (!matches[match[1]]) matches[match[1]] = counter++;
    }
    console.log(matches);
    Object.keys(matches).forEach(function (url) {
        var r = new RegExp("(\\[.*?\\])\\(" + url + "\\)", "g");
        newMarkdown = newMarkdown.replace(r, "$1[" + matches[url] + "]");
        newMarkdown += "\n[" + matches[url] + "]: " + url;
    });

    fs.writeFile(process.argv[3], newMarkdown, 'utf8', function (err) {
        if (err) return console.log(err);
    });

});

function existingRefLinks(markdown) {
    let refLinks = {}, match;
    const matcher = /\[(\d)]:\s(.*)/g; // /\[.*?\]\((.*?)\)/g
    while (match = matcher.exec(markdown)) {
        if (!refLinks[match[1]]) refLinks[match[1]] = match[2];
    }
    markdown = markdown.replaceAll(matcher, "")

    Object.keys(refLinks).forEach(function (int) {
        markdown = markdown.replace("][" + int + "]", "](" + refLinks[int] + ")");
    });
    return markdown
}

请注意,我更喜欢使用@Xunnamius的答案:

npm install --save-dev remark-reference-links remark-cli
npx remark README.md -o --use reference-links

相关问题