Code Monkey home page Code Monkey logo

Comments (28)

W1ndys avatar W1ndys commented on September 16, 2024

右键是可以看到“替换反斜杠为正斜杠”的选项,但实际没效果

from typora_plugin.

obgnail avatar obgnail commented on September 16, 2024

@W1ndys

你好,感谢反馈。

整体流程是没有问题的。应该是你的 callback 函数体写得有问题。

this.utils 里并没有 File 这个对象,具体你可以看一下 .\plugin\global\core\plugin.js 文件里的 utils 类

我将上面的 callback 改成如下,发现是可以的:

callback = anchorNode => {
        alert("this is ReplaceBackslash  callback")
    }

Snipaste_2024-02-08_13-46-41

from typora_plugin.

W1ndys avatar W1ndys commented on September 16, 2024

@W1ndys

你好,感谢反馈。

整体流程是没有问题的。应该是你的 callback 函数体写得有问题。

this.utils 里并没有 File 这个对象,具体你可以看一下 .\plugin\global\core\plugin.js 文件里的 utils 类

我将上面的 callback 改成如下,发现是可以的:

callback = anchorNode => {
        alert("this is ReplaceBackslash  callback")
    }

Snipaste_2024-02-08_13-46-41

谢谢大佬,这是我的相关文件,看不太懂,没理解如何修改,有没有可以凭借学习的文档可以查看。
plugin.zip

from typora_plugin.

obgnail avatar obgnail commented on September 16, 2024

@W1ndys

我帮你打了个样:

class ReplaceBackslash extends BaseCustomPlugin {
    callback = async anchorNode => {
        const filepath = this.utils.getFilePath();
        const content = await this.utils.Package.Fs.promises.readFile(filepath, 'utf-8');
        const replacedContent = this.replaceBackslash(content);
        await this.utils.Package.Fs.promises.writeFile(filepath, replacedContent);
        File.reloadContent(replacedContent, {fromDiskChange: false});
    }

    // 在这里写主要的逻辑代码
    replaceBackslash = content => {
        const replacedContent = content.replace(/\\/g, '/');
        return replacedContent
    }
}

module.exports = { plugin: ReplaceBackslash };

上面代码功能是【将文件中所有的 \ 转换为 /】,并不符合您的预期。

实际上需要修改replaceBackslash方法,先把图片匹配出来,再来替换。

你可以参考 .\plugin\custom\plugins\resourceOperation.js 的做法,它就是先将文件中的图片使用正则匹配出来,再进行其他操作的。

from typora_plugin.

obgnail avatar obgnail commented on September 16, 2024

注意,上面 callback 方法代码的最后一行我写错了,

应该是 File.reloadContent(replacedContent, {fromDiskChange: false});,而不是 File.reloadContent(content, {fromDiskChange: false});

from typora_plugin.

W1ndys avatar W1ndys commented on September 16, 2024

File.reloadContent(replacedContent, {fromDiskChange: false});

!!!!谢谢大佬,功能已经可以正常实现了,接下来就只剩下图片匹配了,谢谢大佬

from typora_plugin.

obgnail avatar obgnail commented on September 16, 2024

File.reloadContent(replacedContent, {fromDiskChange: false});

!!!!谢谢大佬,功能已经可以正常实现了,接下来就只剩下图片匹配了,谢谢大佬

匹配图片有个难点:

  • 此插件的难点在于如何才能匹配到正确的 markdown 图片
  • 比如 ![image](assets/image (30).png) ,使用正则很容易匹配成 ![image](assets/image (30
  • 此时需要使用贪婪匹配,然后逐个匹配
  • 可以使用如下正则去匹配 regexp = new RegExp("!\\[.*?\\]\\((?<src1>.*)\\)", "g")

具体可以参考 .\plugin\custom\plugins\resourceOperation.js 的做法

from typora_plugin.

W1ndys avatar W1ndys commented on September 16, 2024
  • regexp = new RegExp("!\[.?\]\((?.)\)", "g")

谢谢大佬,我的问题已经解决了,您真是我的救星

image

from typora_plugin.

W1ndys avatar W1ndys commented on September 16, 2024
class ReplaceBackslash extends BaseCustomPlugin {
    callback = async anchorNode => {
        const filepath = this.utils.getFilePath();
        const content = await this.utils.Package.Fs.promises.readFile(filepath, 'utf-8');
        const replacedContent = this.replaceBackslash(content);
        await this.utils.Package.Fs.promises.writeFile(filepath, replacedContent);
        File.reloadContent(replacedContent, {fromDiskChange: false});
    }

    // 在这里写主要的逻辑代码
    replaceBackslash = content => {
        const regexp = /!\[(.*?)\]\((.*?)\)/g;
        const replacedContent = content.replace(regexp, (match, desc, src) => {
            // 对图片路径中的反斜杠进行替换
            const replacedSrc = src.replace(/\\/g, '/');
            return `![${desc}](${replacedSrc})`;
        });
        return replacedContent;
    }
}

module.exports = { plugin: ReplaceBackslash };

这是代码

from typora_plugin.

obgnail avatar obgnail commented on September 16, 2024

好的。此 issue 关闭,有问题麻烦在下面留言,或者另开 issue。

from typora_plugin.

W1ndys avatar W1ndys commented on September 16, 2024

好的。此 issue 关闭,有问题麻烦在下面留言,或者另开 issue。

大佬你好,还有一个新的疑问,我如何把写好的功能添加到typora右下角的按钮中,开发文档里没有找到相关的介绍
image

from typora_plugin.

obgnail avatar obgnail commented on September 16, 2024

@W1ndys

负责此功能的是 quickButton 插件,你可以通过修改配置添加。

对于你的情况,你可以在 custom_plugin.user.toml 添加如下配置:

[quickButton]
[quickButton.config]
#   disable:      禁用此按钮
#   coordinate:   按钮坐标。往上为x轴正方向,往左为y轴正方向,从零开始计数
#   icon:         按钮图标。填入css class。支持font-awesome-4.1.0和ionicons-2.0.1,所有的图标及其对应的css class请参考:https://www.adfwebmagazine.jp/wp-content/uploads/test_v4.1.pdf  和  https://ionic.io/ionicons/v2
#   size(可选):    图标大小。默认17px
#   color(可选):   图标颜色。默认跟随当前主题的配色方案
#   bgColor(可选): 图标背景色。默认跟随当前主题的配色方案
#   hint:         提示信息
#   callback:     回调函数。采用pluginName.MethodName的形式(功能就像hotkey.default.toml中的plugin参数和function参数的合体)
#                     MethodName请通过阅读源码查找。如果您不懂代码,但还是想添加按钮,有个碰运气技巧:在【右键菜单->常用插件->自定义插件下的插件】基本都是XXX.callback,其余插件基本都是XXX.call
#   evil(危险):    自定义回调函数。功能同hotkey.default.toml中的evil参数(它能用的,这里也能用)。这里的文本内容会被eval()。如果设置此参数,callback参数会失效
buttons = [
    # 默认的按钮
    { disable = false, coordinate = [0, 0], hint = "直达底部", size = "28px", icon = "fa fa-angle-down", callback = "go_top.goBottom" },
    { disable = false, coordinate = [1, 0], hint = "直达顶部", size = "28px", icon = "fa fa-angle-up", callback = "go_top.goTop" },
    { disable = false, coordinate = [2, 0], hint = "文字风格", size = "17px", icon = "fa fa-font", callback = "text_stylize.call" },
    { disable = false, coordinate = [3, 0], hint = "混排优化", size = "17px", icon = "fa fa-align-justify", callback = "md_padding.call" },
    { disable = false, coordinate = [0, 1], hint = "思维导图", size = "22px", icon = "fa fa-code-fork", callback = "markmap.onButtonClick" },
    { disable = false, coordinate = [1, 1], hint = "图片管理", size = "17px", icon = "fa fa-image", callback = "imageReviewer.callback" },
    { disable = false, coordinate = [2, 1], hint = "书签管理", size = "17px", icon = "fa fa-bookmark", callback = "scrollBookmarker.callback" },
    { disable = false, coordinate = [3, 1], hint = "高亮搜索", size = "17px", icon = "fa fa-search", callback = "search_multi.call" },

    # 你的按钮
    { disable = false, coordinate = [4, 1], hint = "正斜杠替换斜杠", size = "17px", icon = "fa fa-book", callback = "ReplaceBackslash.callback" },
]

from typora_plugin.

W1ndys avatar W1ndys commented on September 16, 2024

已实现,谢谢dalao,大佬太细心了,轮子都给我造好了
image

我不会pr,稍后我可能会写个文档发在issues,因为我做这个插件是用来替换Hexo博客图片路径的,希望能帮到同样有这个需求的的Hexo用户

from typora_plugin.

obgnail avatar obgnail commented on September 16, 2024
  1. 刚刚上面的配置又写错了 😂,是 # 默认的按钮,不是 // 默认的按钮,请看一下编辑历史
  2. 具体的参数你可以看一下上面的注释中的说明
  3. 如有必要,你可以删除默认的按钮(disable置为true),全部都是可配置的。

from typora_plugin.

W1ndys avatar W1ndys commented on September 16, 2024
  1. 刚刚上面的配置又写错了 😂,是 # 默认的按钮,不是 // 默认的按钮,请看一下编辑历史
  2. 具体的参数你可以看一下上面的注释中的说明
  3. 如有必要,你可以删除默认的按钮(disable置为true),全部都是可配置的。

没有造成什么错误,大佬修改的很快,我看到的时候就已经改正确了🤭
谢谢大佬的耐心回复,又是一次酣畅淋漓的学习

from typora_plugin.

obgnail avatar obgnail commented on September 16, 2024

稍后我可能会写个文档发在 issues,因为我做这个插件是用来替换 Hexo 博客图片路径的,希望能帮到同样有这个需求的的 Hexo 用户

好的。麻烦你了。

from typora_plugin.

obgnail avatar obgnail commented on September 16, 2024

@W1ndys

//————注意————,这里的 img 路径可以替换为你自己实际的路径

给个建议,插件本身是可以添加配置选项的,可以将硬编码的配置提到 custom_plugin.user.toml 中


示例代码:

# ./plugin/custom/custom_plugin.user.toml

[helloWorld]
name = "你好世界"
enable = true

	[helloWorld.config]
	show_message = "this is hello world plugin"
// ./plugin/custom/plugins/helloWorld.js

class helloWorld extends BaseCustomPlugin {
    callback = anchorNode => {
        alert(this.config.show_message);
    }
}

module.exports = { plugin: helloWorld };

from typora_plugin.

obgnail avatar obgnail commented on September 16, 2024

还有英雄所见略同的一点就是,几年以前,我也整过 hexo 的自动化部署,果然大家都比较懒 😂

事实是,就算有了自动化部署工具,我的博客也停在了 2022 年(悲

from typora_plugin.

W1ndys avatar W1ndys commented on September 16, 2024

@W1ndys

//————注意————,这里的 img 路径可以替换为你自己实际的路径

给个建议,插件本身是可以添加配置选项的,可以将硬编码的配置提到 custom_plugin.user.toml 中

示例代码:

# ./plugin/custom/custom_plugin.user.toml

[helloWorld]
name = "你好世界"
enable = true

	[helloWorld.config]
	show_message = "this is hello world plugin"
// ./plugin/custom/plugins/helloWorld.js

class helloWorld extends BaseCustomPlugin {
    callback = anchorNode => {
        alert(this.config.show_message);
    }
}

module.exports = { plugin: helloWorld };

没太懂大佬的意思,是说插件本身是有相关配置可以提示信息的吗?

from typora_plugin.

W1ndys avatar W1ndys commented on September 16, 2024

还有英雄所见略同的一点就是,几年以前,我也整过 hexo 的自动化部署,果然大家都比较懒 😂

事实是,就算有了自动化部署工具,我的博客也停在了 2022 年(悲

我自从到24年,就已经逐渐开始走脚本化Hexo了😂,部署啥的指令全让我写成sh脚本了,鼠标点两下就完事

from typora_plugin.

W1ndys avatar W1ndys commented on September 16, 2024

给个建议,插件本身是可以添加配置选项的,可以将硬编码的配置提到 custom_plugin.user.toml 中

我懂了,其实我想中的提示信息是可以实现[通过]样式的提示弹窗,alert的弹窗是警告,有种没执行成功的感觉😂
百度了一下发现js没有类似通过的弹窗(好像)

from typora_plugin.

obgnail avatar obgnail commented on September 16, 2024

其实我的意思是,你的新的 issue 中,可以将代码中硬编码的 /img/ 改成一个配置选项,毕竟每个人的 hexo 配置都不一样

from typora_plugin.

W1ndys avatar W1ndys commented on September 16, 2024

其实我的意思是,你的新的 issue 中,可以将代码中硬编码的 /img/ 改成一个配置选项,毕竟每个人的 hexo 配置都不一样

明白了,这样写可以吗,对插件的配置刚接触,目前我只想到了这种方式

[ReplaceBackslash.config]
img = "img"

然后this.config.img作为代码中的变量

然后让使用者去改对应的值

from typora_plugin.

obgnail avatar obgnail commented on September 16, 2024

对的

from typora_plugin.

W1ndys avatar W1ndys commented on September 16, 2024

对的

我已经重写完了,实现了这个功能,稍后我修改一下文档

from typora_plugin.

W1ndys avatar W1ndys commented on September 16, 2024

@obgnail
大佬,我刚刚测试的时候发现,图片路径匹配还是写的不好,没法精准匹配到图片路径,这个操作连我的代码块,其他斜杠也给改掉了,实在是不会解决了,求助一下
#469

from typora_plugin.

obgnail avatar obgnail commented on September 16, 2024

@W1ndys

其实这个需求还蛮难的:

  1. 需要考虑到 <img src="example.jpg"> 的 HTML 图片的情况
  2. 需要考虑到图片的路径中存在右括号的情况: ![image](assets/image (1).png),此时图片路径中的右括号会和图片语法中 []() 的右括号造成歧义
  3. 需要考虑特殊格式的图片(如base64)和网络图片

重点说明一下如何解决第二点:

  1. 贪婪匹配。如下内容 ![image](assets/image (30).png)asdasdasdasd)aaaaa,使用贪婪匹配会得到 ![image](assets/image (30).png)asdasdasdasd)
  2. 从右往左依次重新贪婪匹配,然后挨个检测文件是否存在,一旦检测到文件存在,则返回:
    1. ![image](assets/image (30).png)asdasdasdasd),检测是否存在文件 assets/image (30).png)asdasdasdasd
    2. ![image](assets/image (30).png),检测是否存在文件 assets/assets/image (30).png
    3. ![image](assets/image (30),检测是否存在文件 assets/image (30

爬起来帮你写了一个框架,我没仔细测试,我并不了解具体业务,需要你自行编写replaceBackslash函数:

[ReplaceBackslash]
name = "替换反斜杠为正斜杠"
enable = true

[ReplaceBackslash.config]
# 是否忽略html标签<img src="example.jpg">里的资源(markdown是支持插入html的,此选项问是否要忽略img标签)
ignore_image_div = false
img_folder = "img"
class ReplaceBackslash extends BaseCustomPlugin {
    callback = async anchorNode => {
        const filepath = this.utils.getFilePath();
        const content = await this.utils.Package.Fs.promises.readFile(filepath, 'utf-8');
        const replacedContent = await this.format(content);
        await this.utils.Package.Fs.promises.writeFile(filepath, replacedContent);
        File.reloadContent(replacedContent, {fromDiskChange: false});
    }

    format = async content => {
        const dir = this.utils.getCurrentDirPath();
        const regexp = this.config.ignore_image_div
            ? new RegExp("!\\[.*?\\]\\((?<src1>.*)\\)", "g")
            : new RegExp("!\\[.*?\\]\\((?<src1>.*)\\)|<img.*?src=\"(?<src2>.*?)\"", "g")

        return await this.asyncReplace(content, regexp, async (match, src1, src2) => {
            const src = src1 || src2;

            // 跳过特殊格式的图片(如base64)和网络图片
            if (!src || this.utils.isSpecialImage(src) || this.utils.isNetworkImage(src)) return match;

            // 检测图片是否存在于当前电脑中,若不存在,则不处理
            // 如果不希望检测,可以注释掉下面两行
            const realPath = await this.checkImageExist(dir, src);
            if (!realPath) return match;

            return this.replaceBackslash(match, src, realPath);
        })
    }

    // TODO: 我并不了解具体业务,需要你自行编写(下面函数代码是瞎写的)
    // 当前可以使用的变量
    //   1. match: 匹配到子串,如: ![image](assets/image (30).png)
    //   2. src: 匹配到的路径,如:assets/image (30).png
    //   3. realPath: 图片在电脑中的绝对路径,如:D:\\assets\\image (30).png
    replaceBackslash = (match, src, realPath) => {
        const imgFolder = this.config.img_folder;
        if (src.includes('/' + imgFolder + '/')) {
            const newSrc = '/' + imgFolder + src.substring(src.indexOf('/' + imgFolder + '/') + imgFolder.length + 1);
            const index = match.indexOf(src);
            return match.slice(0, index) + match.slice(index).replace(src, newSrc)
        }
        return match
    }

    asyncReplace = (content, regexp, placement) => {
        let match;
        let lastIndex = 0;
        const reg = new RegExp(regexp);
        const promises = [];

        while ((match = reg.exec(content))) {
            const str = content.slice(lastIndex, match.index);
            lastIndex = reg.lastIndex;
            const args = [...match, match.index, match.input];
            if (match.groups) {
                args.push(match.groups);
            }
            const promise = placement(...args);
            promises.push(str, promise);
        }
        promises.push(content.slice(lastIndex));
        return Promise.all(promises).then(results => results.join(""))
    }

    checkImageExist = async (currentDir, path) => {
        let absolutePath = this.utils.Package.Path.resolve(currentDir, path);

        while (!(await this.utils.existPath(absolutePath))) {
            const idx = absolutePath.lastIndexOf(")");
            if (idx === -1) {
                return new Promise(resolve => resolve(null))
            } else {
                absolutePath = absolutePath.slice(0, idx);
            }
        }
        return new Promise(resolve => resolve(absolutePath))
    }
}

module.exports = {plugin: ReplaceBackslash};

from typora_plugin.

W1ndys avatar W1ndys commented on September 16, 2024

@obgnail
😭😭😭😭
大佬太强了,大佬给写的轮子已经实现了,我只吧路径路径简单修改了一下就完全实现了,代码我已经同步更新到文档了
#469

看了一下和之前提到的图片匹配的脚本,还是不会复刻,发现这还真是我知识盲区了,没接触过js,都是凭借着编码经验+大佬的帮助+ChatGPT解决的

大佬新年快乐

from typora_plugin.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.