V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
lisongeee
V2EX  ›  分享创造

什么才是开发油猴脚本最好的体验

  •  
  •   lisongeee ·
    lisonge · 2022-05-09 11:05:25 +08:00 · 4477 次点击
    这是一个创建于 690 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我发现现有的辅助油猴脚本开发的体验都一言难尽

    比如需要手动配置 UserScript ,我为什么不能自动配置自动在浏览器打开呢,配置更改的时候也自动在浏览器打开

    还有 @require 的配置,我为什么不能在插件里配置库的 cdn 链接,然后自动注入 UserScript 。而且这个是随打包的版本确定的,不是静态的

    还有开发时热重载的体验,我想要类似开发 vue/react 项目的正常体验,大多数操作只需要局部刷新,不需要刷新宿主页面

    因此为了实现这些良好的体验,我开发了一个 vite 插件

    https://github.com/lisonge/vite-plugin-monkey/blob/main/README_zh.md

    得益于 vite 明确区分了 server 和 build 的良好架构,

    只要稍做配置,你甚至能将现有的 vue/react 项目直接转成 油猴脚本

    当然有什么用的不舒适的地方可以直接指出
    52 条回复    2023-05-23 12:58:21 +08:00
    statumer
        1
    statumer  
       2022-05-09 11:43:54 +08:00 via iPhone
    看着很棒啊
    lisongeee
        2
    lisongeee  
    OP
       2022-05-09 11:47:34 +08:00
    @statumer
    哈哈谢谢,有空可以用一下,最近在 mo🐟,想改进一下这个插件,奈何用的人比较少
    golangLover
        3
    golangLover  
       2022-05-09 12:34:55 +08:00
    你这 TS definition 写的好仔细啊。赞一个
    yunser
        4
    yunser  
       2022-05-09 12:56:27 +08:00
    刚好最近想要写一个 UserScript ,试用了一下。体验非常好,以后就用这个了。
    lyxeno
        5
    lyxeno  
       2022-05-09 13:33:41 +08:00
    已 star,有空试用一下
    xujiahui
        6
    xujiahui  
       2022-05-09 13:53:40 +08:00
    虽然没开发过油猴脚本,但是这个项目看着很不错,以后学习下
    Johnming
        7
    Johnming  
       2022-05-10 11:09:05 +08:00
    感觉很棒,可以试试
    lisongeee
        8
    lisongeee  
    OP
       2022-05-12 11:39:46 +08:00
    更新了一下,优化了一些问题
    lisongeee
        9
    lisongeee  
    OP
       2022-08-05 10:49:23 +08:00
    更新了一下,又优化了一些问题,目前正在完善 GM_api 的类型注释和 让其支持 esm 引入

    <https://github.com/lisonge/vite-plugin-monkey>
    lisongeee
        10
    lisongeee  
    OP
       2022-08-10 11:30:17 +08:00
    更新:现在支持使用 esm 使用 GM_api
    lisongeee
        14
    lisongeee  
    OP
       2022-08-18 17:09:54 +08:00
    lisongeee
        15
    lisongeee  
    OP
       2022-08-18 17:14:51 +08:00
    lisongeee
        16
    lisongeee  
    OP
       2022-08-18 17:32:11 +08:00
    # vite-plugin-monkey

    <p>
    <a href="https://www.npmjs.com/package/vite-plugin-monkey"><img src="https://img.shields.io/npm/v/vite-plugin-monkey.svg" alt="npm package"></a>
    <a href="https://github.com/lisonge/vite-plugin-monkey/releases/"><img src="https://img.shields.io/node/v/vite-plugin-monkey.svg" alt="node compatibility"></a>
    </p>

    [README](README.md) | [中文文档](README_zh.md)

    vite plugin server and build \*.user.js for [Tampermonkey]( https://www.tampermonkey.net/) and [Violentmonkey]( https://violentmonkey.github.io/) and [Greasemonkey]( https://www.greasespot.net/)

    ## feature

    - support Tampermonkey and Violentmonkey and Greasemonkey
    - inject userscript comment to build bundle
    - auto open \*.user.js in default browser when userscript change
    - external cdn url inject to userscript @require
    - use GM_api by ESM import with type hints
    - when vite preview, auto open browser install dist.user.js
    - full typescript support and vite feature


    https://i.songe.li/1x1.png#IyB2aXRlLXBsdWdpbi1tb25rZXkKCjxwPgogIDxhIGhyZWY9Imh0dHBzOi8vd3d3Lm5wbWpzLmNvbS9wYWNrYWdlL3ZpdGUtcGx1Z2luLW1vbmtleSI+PGltZyBzcmM9Imh0dHBzOi8vaW1nLnNoaWVsZHMuaW8vbnBtL3Yvdml0ZS1wbHVnaW4tbW9ua2V5LnN2ZyIgYWx0PSJucG0gcGFja2FnZSI+PC9hPgogIDxhIGhyZWY9Imh0dHBzOi8vZ2l0aHViLmNvbS9saXNvbmdlL3ZpdGUtcGx1Z2luLW1vbmtleS9yZWxlYXNlcy8iPjxpbWcgc3JjPSJodHRwczovL2ltZy5zaGllbGRzLmlvL25vZGUvdi92aXRlLXBsdWdpbi1tb25rZXkuc3ZnIiBhbHQ9Im5vZGUgY29tcGF0aWJpbGl0eSI+PC9hPgo8L3A+CgpbUkVBRE1FXShSRUFETUUubWQpIHwgW+S4reaWh+aWh+aho10oUkVBRE1FX3poLm1kKQoKdml0ZSBwbHVnaW4gc2VydmVyIGFuZCBidWlsZCBcKi51c2VyLmpzIGZvciBbVGFtcGVybW9ua2V5XShodHRwczovL3d3dy50YW1wZXJtb25rZXkubmV0LykgYW5kIFtWaW9sZW50bW9ua2V5XShodHRwczovL3Zpb2xlbnRtb25rZXkuZ2l0aHViLmlvLykgYW5kIFtHcmVhc2Vtb25rZXldKGh0dHBzOi8vd3d3LmdyZWFzZXNwb3QubmV0LykKCiMjIGZlYXR1cmUKCi0gc3VwcG9ydCBUYW1wZXJtb25rZXkgYW5kIFZpb2xlbnRtb25rZXkgYW5kIEdyZWFzZW1vbmtleQotIGluamVjdCB1c2Vyc2NyaXB0IGNvbW1lbnQgdG8gYnVpbGQgYnVuZGxlCi0gYXV0byBvcGVuIFwqLnVzZXIuanMgaW4gZGVmYXVsdCBicm93c2VyIHdoZW4gdXNlcnNjcmlwdCBjaGFuZ2UKLSBleHRlcm5hbCBjZG4gdXJsIGluamVjdCB0byB1c2Vyc2NyaXB0IEByZXF1aXJlCi0gdXNlIEdNX2FwaSBieSBFU00gaW1wb3J0IHdpdGggdHlwZSBoaW50cwotIHdoZW4gdml0ZSBwcmV2aWV3LCBhdXRvIG9wZW4gYnJvd3NlciBpbnN0YWxsIGRpc3QudXNlci5qcwotIGZ1bGwgdHlwZXNjcmlwdCBzdXBwb3J0IGFuZCB2aXRlIGZlYXR1cmU=
    lisongeee
        17
    lisongeee  
    OP
       2022-08-18 17:51:57 +08:00
    lisongeee
        18
    lisongeee  
    OP
       2022-08-18 21:05:33 +08:00
    lisongeee
        19
    lisongeee  
    OP
       2022-08-19 18:37:05 +08:00
    测试 `tab` 缩进是否会被去掉
    ```ts
    (() => {
    const blankReg = /[\n\r]+/g;
    Array.from(
    document.querySelectorAll<HTMLElement>('div.reply_content')
    ).forEach((div) => {
    const mdText = div.innerText;
    const article = document.createElement('article');
    article.classList.add('markdown-body');
    article.innerHTML = 'markdownItInstance.render(mdText)';
    if (
    article.innerText.replace(blankReg, '') == mdText.replace(blankReg, '')
    ) {
    // 渲染后无变化不执行替换
    return;
    }
    article.style.width = '100%';
    div.innerHTML = '';
    div.classList.add('v2ex-comment-markdown');
    div.appendChild(article);
    });
    })();

    ```
    lisongeee
        20
    lisongeee  
    OP
       2022-08-19 18:40:14 +08:00
    测试微博图床链接是否会被 v2 转成图片

    >

    lisongeee
        21
    lisongeee  
    OP
       2022-08-19 18:44:36 +08:00
    ?k=v#hashaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    wxf666
        22
    wxf666  
       2022-08-19 19:08:06 +08:00
    测试 # 后跟 base64

    #base64

    测试主机名后直接跟 base64

    https://sinaimg.cn/base64

    https://wx3.sinaimg.cn/base64
    wxf666
        23
    wxf666  
       2022-08-19 19:10:21 +08:00
    这是直接吃掉微博图片了吗

    测试主机名后跟两个 base64

    https://sinaimg.cn/base64/base64

    https://wx3.sinaimg.cn/base64/base64
    lisongeee
        24
    lisongeee  
    OP
       2022-08-19 19:40:33 +08:00
    测试把 base64 放在 basename 上,这是错误的图片链接

    lisongeee
        25
    lisongeee  
    OP
       2022-08-19 19:44:39 +08:00
    @wxf666

    还有一个方法就是把 base64 放在 `wx3.sinaimg.cn/mw2000/${base64Str}.jpg` 这样

    然后 v2 会自己把这个链接转图片,好处是 源信息传递出去了

    坏处是在外部视角你发的这条评论 底部会显示一个裂开的图片,具体效果是这样

    wxf666
        26
    wxf666  
       2022-08-19 20:30:59 +08:00
    @lisongeee 要不,用点零宽字符啥的?*(但零宽字符太少了)*

    或者,引入压缩库?*(感觉短文本压缩效率应该也不理想)*

    那摸清会吃掉哪些字符*(如行首空格,连续空格)*,提前用零宽字符代替?
    lisongeee
        27
    lisongeee  
    OP
       2022-08-22 10:24:06 +08:00
    lisongeee
        28
    lisongeee  
    OP
       2022-08-22 10:24:21 +08:00
    lisongeee
        29
    lisongeee  
    OP
       2022-08-22 10:24:35 +08:00
    lisongeee
        30
    lisongeee  
    OP
       2022-08-22 10:25:49 +08:00
    lisongeee
        32
    lisongeee  
    OP
       2022-08-22 10:27:50 +08:00
    lisongeee
        33
    lisongeee  
    OP
       2022-08-22 10:28:07 +08:00
    lisongeee
        35
    lisongeee  
    OP
       2022-08-22 10:32:51 +08:00
    lisongeee
        36
    lisongeee  
    OP
       2022-08-22 10:33:14 +08:00
    lisongeee
        37
    lisongeee  
    OP
       2022-08-22 11:12:44 +08:00
    ```ts
    const mdCodeReg = /```.+?```/g;
    const replyForm = document.querySelector<HTMLFormElement>(`#reply-box form`)!;
    const textarea = replyForm.querySelector('textarea')!;
    replyForm.addEventListener('submit', () => {
    if (!mdCodeReg.test(textarea.value)) {
    return;
    }

    textarea.value +=
    '\n' +
    `https://wx3.sinaimg.cn/base62/${base62.encode(
    tec.encode(textarea.value)
    )}.jpg`;
    });
    ```
    lisongeee
        38
    lisongeee  
    OP
       2022-08-22 11:26:38 +08:00
    lisongeee
        39
    lisongeee  
    OP
       2022-08-22 11:33:27 +08:00
    @wxf666

    我尝试使用 ·https://wx3.sinaimg.cn/base62/ xxx .jpg` 去保存信息,但是一旦使用次数过多,v2 便会提醒不要在评论中包含外链,所以用图片保存信息不太行
    lisongeee
        40
    lisongeee  
    OP
       2022-08-22 15:56:23 +08:00
    # 代码高亮及其自动格式化测试

    ## js

    ```js
    const markdownItInstance = markdownit({
    highlight(str, lang) {
    lang = lang.toLowerCase();
    if (lang2parser[lang]) {
    console.log({ str, lang });
    try {
    str = prettier.format(str, {
    parser: lang2parser[lang],
    plugins,
    });
    } catch {}
    }
    if (lang && hljs.getLanguage(lang)) {
    try {
    return hljs.highlight(str, { language: lang }).value;
    } catch (__) {}
    }
    return '';
    },
    });
    ```

    ## ts

    ```ts
    const plugins: Plugin[] = [
    parserBabel,
    parserYaml,
    parserHtml,
    parserPostcss,
    parserJava,
    ];

    const lang2parser: Record<string, BuiltInParserName | string> = {
    js: 'babel',
    jsx: 'babel',
    ts: 'babel-ts',
    tsx: 'babel-ts',
    json: 'json',
    json5: 'json5',
    yaml: 'yaml',
    html: 'html',
    vue: 'vue',
    scss: 'scss',
    css: 'css',
    less: 'less',
    java: 'java',
    };
    ```

    ## Java

    ```java
    public class HelloWorld {
    public static void main(String[] args) {System.out.println("Hello World!");;;;;}

    @Override
    public String toString() {
    return "Hello World";
    }
    public int sum(int argument1,int argument2,int argument3,int argument4,int argument5
    ) {
    return argument1+argument2+ argument3 +argument4 + argument5;
    }
    }
    ```
    wxf666
        41
    wxf666  
       2022-08-22 22:10:55 +08:00
    @lisongeee 我觉得在行首 /多个空白字符间,加入零宽字符,是可取的。如:

    > <零宽><空格><零宽><空格><零宽><空格><零宽><空格>return<空格>'ok'

    插件去掉 <零宽> 后,就能让代码渲染器正常工作了


    优点:

    1. <空格>应该不会被 v 站 吃掉
    2. 对于未装插件的人而言,视觉上没有影响
    3. 额外占用的空间不多


    缺点:

    1. 未装插件的人,直接复制代码,会有<零宽>阻碍正常运行,但又肉眼不可见,可能找不到问题所在?
    lisongeee
        42
    lisongeee  
    OP
       2022-08-23 14:21:58 +08:00
    @wxf666

    v1.1.0 更新日志
    由于 V2EX 会删除评论代码缩进, 因此插件会自动格式化代码, 支持的语言有 js/jsx/ts/tsx/json/json5/html/vue/scss/css/less/java
    ltkun
        43
    ltkun  
       2022-08-23 15:49:06 +08:00
    ### 帅气的 OP!
    duanluan
        44
    duanluan  
       2022-09-23 17:00:37 +08:00
    有没有交流群或者什么的
    lisongeee
        45
    lisongeee  
    OP
       2022-09-23 17:12:52 +08:00
    @duanluan 这东西要啥交流群啊?有问题直接去 issues 问就行,个人感觉交流群没有代码的感觉
    duanluan
        46
    duanluan  
       2022-09-23 17:20:39 +08:00
    @lisongeee issues 提使用上的疑问总感觉有点突兀,搞个交流群也适合快速反馈想法、问题,也方便新手更快入门,就坚持使用下来了。
    lisongeee
        47
    lisongeee  
    OP
       2022-09-23 17:36:56 +08:00
    谢谢,你说的交流群我感觉更适合 app 这种较大型项目,我这个插件并没有很多功能,我觉得文档和例子已经很详细

    不过我刚刚把项目的 [discussions]( https://github.com/lisonge/vite-plugin-monkey/discussions) 打开了,不想用 issues 可以用这个

    其实我仔细思考了一下,觉得你说的还是挺有道理的,但我是个咸鱼懒狗,对交流群这种兴趣不大,抱歉
    duanluan
        48
    duanluan  
       2022-09-23 17:38:45 +08:00
    就是你回复过我的主题,你也看到了我那个仓库是一个 webpack 底下有多个 tampermonkey 项目,然后还有公共的 utils 目录,同时设置了别名,以供这三个项目调用,但是用 vite 的话我就不太清楚要怎么搞了,不太好迁移。
    lisongeee
        49
    lisongeee  
    OP
       2022-09-23 17:57:54 +08:00
    @duanluan
    > 就是你回复过我的主题,你也看到了我那个仓库是一个 webpack 底下有多个 tampermonkey 项目,然后还有公共的 utils 目录,同时设置了别名,以供这三个项目调用,但是用 vite 的话我就不太清楚要怎么搞了,不太好迁移。

    我认为 `单个仓库里有多个油猴脚本的项目结构` 其实很适合 我这个插件使用的 pnpm [monorepo]( https://juejin.cn/post/6944877410827370504) ,这个和用 vite 还是 webpack 构建没有关系。

    vue/vite/element/react 以及很多知名的框架都是这种 monorepo 结构,评论篇幅太小不好展开说

    至于你说的 `不太好迁移` ,如果你乐意,我可以帮你迁移并发起 pulls
    duanluan
        50
    duanluan  
       2022-09-23 18:05:27 +08:00
    @lisongeee
    > 我可以帮你迁移并发起 pulls
    好耶!那自然是最好啦!!
    lisongeee
        51
    lisongeee  
    OP
       2022-09-24 17:58:29 +08:00
    @duanluan
    > 好耶!那自然是最好啦!!

    <https://github.com/duanluan/tampermonkey-scripts/pull/1>
    xpy0313
        52
    xpy0313  
       311 天前
    mark ,我也开发了好几个自用的油猴脚本了,每次都是从 0 开始,甚至 ui 都是纯 js 撸,太 low 了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2822 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 43ms · UTC 14:55 · PVG 22:55 · LAX 07:55 · JFK 10:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.