Copyq如何复制网页内容的时候,提出url写入meta中?还有切换置顶功能

1 copyq如何复制网页内容的时候,提出url写入meta中?

在官网的commands中找到可以添加 来源app的名字和 写入的时间

自己尝试用ai辅助增加一个 来源的网页网址,但是提取不到. ( 其他类似剪贴板工具都可以提取到)

有没有大佬能解决?

2 如何实现切换置顶功能

目前只能通过 两条独立命令实现

copyq config close_on_unfocus true

copyq config close_on_unfocus false

而使用ai写的脚本(js) 调用copyq的api 无法设置这个属性.

有没有佬知道?

问了AI:https://www.qianwen.com/share?shareId=dfe9f0bd-6e29-4373-a0a3-b1da545ce77b

在 CopyQ(GitHub 项目:hluk/CopyQ)中,从浏览器复制内容时自动提取网页 URL 并作为剪贴板条目的元数据(meta information),是通过监听系统剪贴板中的特定 MIME 格式(如 text/html)并解析其中的 标签或上下文信息来实现的。

具体实现机制如下:
. 监听剪贴板格式

CopyQ 会监控剪贴板中多种格式的数据,包括:

text/plain
text/html
自定义格式(如来自 Chrome/Firefox 的私有格式)

当用户从浏览器(如 Chrome、Firefox)复制一段带格式的内容时,剪贴板通常会同时包含 text/html 和 text/plain,有时还会附带额外的私有格式(如 application/x-moz-nativehtml 或 chromium/x-renderer-taint),但最关键的是 text/html。
. 解析 HTML 内容以提取来源 URL

在源码中,相关逻辑主要位于以下文件:

src/item/itemfactory.cpp
src/common/mimetypes.cpp
src/scriptable/scriptableitem.cpp

但最关键的提取逻辑是在 HTML 解析器 和 元数据处理 部分,尤其是通过正则或 Qt 的 QRegularExpression 提取 <meta property=“og:url” …> 或 等标签。

然而,更直接的实现方式是利用 Qt 的 QMimeData 中的 text/html 数据本身可能包含注释或结构化信息,或者依赖于 浏览器在 HTML 片段开头插入的注释。

copyq提取的 mime text/html 片段里面没有 meta信息, 但是其他剪贴板软件提取同样的内容是包含的, 所以别的软件都可以提取到.

实际上copyq这个玩意特别傻. 看起来支持脚本, 命令各种操控

实际各方面都差点意思.

脚本不能设置/读取copyq自己的全局参数

命令不能使用 flow逻辑 不支持变量传递.

置顶功能都没有直接暴露.

各种反人类设计.

如果你想使用其他支持编程的剪贴板工具,我推荐

其实我目前的主力方案是 clipcache + 同步(ditto) + quicker(调用python 处理剪贴板文本).

这次想换到copyq 主要是看前几天大家说可以用python代码处理剪贴板啦内容, 这样正好可以复用我目前方案中的python代码. 而实际使用copyq来看, 很多使用逻辑反人类.

市面上几乎没有能替代clipcache的产品

目前只有clipcache 支持针对复制的程序指定获取哪几种格式的剪贴板内容

同时可以对粘贴到具体的程序指定 粘贴快捷键(部分程序不支持ctrl+v , 或者shift+insert).

我的电脑里有3个剪贴板工具

image.png

这里面 clipcache 的确是最省心的. 但是, 它对png图片的支持有问题, 无法粘贴透明图片.

ClipboardFusion 支持C#/VB.net, 但是不支持图片同步.

copyQ 支持的最好, 但是代码自称风格, 而且最近的几版性能有问题.

我的组合是 clipcache+ ditto .

你说的png带aplha透明的问题我似乎没遇到. 可能没怎么用png带透明的把.

反正粘贴不行的 都是clipcache选中要贴的图,然后用quicker 有个获取原图再再贴的方法 贴图就没有问题了.

难受的风格

clipboard('text/x-moz-url-priv')可以获取当前剪贴板网页内容的来源链接
data()input()都不行……

1 str(data(mimeWindowTitle)) 可以获取窗口标题,从 Edge 复制时只包括主域名,之后可以用正则匹配。或者,找到类似 @allor 回复的 text/x-moz-url-priv 这种私有 MIME(这应该是火狐浏览器的),也应该可以匹配上。

2 切换置顶可以使用下面的命令:

[Command]
Name=切换置顶状态
MatchCommand="
    copyq:
    var on = config(\"always_on_top\") === \"true\"
    if (on) {
      menuItem['text'] = '取消置顶'
      menuItem['tag'] = 'x'
    } else {
      menuItem['text'] = '置顶窗口'
      menuItem['tag'] = ''
    }"
Command="
    copyq:
    var rows = selectedItems()
    var on = config(\"always_on_top\") === \"true\"

    config(\"always_on_top\", !on)
    config(\"activate_closes\",on)
    config(\"close_on_unfocus\",on)

    selectItems.apply(this, rows)"
InMenu=true
Icon=
Shortcut=ctrl+`

3 针对你的其他问题:

脚本不能设置/读取copyq自己的全局参数

这个完全通过 settings()config() 进行设置。

命令不能使用 flow逻辑 不支持变量传递.

不懂什么时 flow 逻辑,但是单个脚本内的函数可以直接传参,跨脚本可以通过 settings(var) 或 全局脚本的形式间接实现 。

置顶功能都没有直接暴露.

这个确实有点问题,CopyQ 的窗口置顶实际和另外两个设置相关 activate_closes 和 close_on_unfocus ,需要同时修改才能达到我们正常理解的窗口置顶效果。

谢谢啊,

2 置顶非常棒

1 firefox可以用**text/x-moz-url-priv , chrome系列都不行, ai还提供一个方案通过油猴写一条这个格式的数据到剪贴板, 但是chrome中copyq还是获取不到.**

有别的办法吗?

data(MimeType) 被 CopyQ 预处理过,要获取剪贴板原始数据得用 clipboard(MimeType)

Firefox 的来源网址存储在 text/x-moz-url-priv,Chromium 是 text/_chromium-source-url。不过最靠谱的还是从 HTML Format 里提取,因为 Chromium 返回的不一定是有效网址,比如 VSCode 就可能返回 vscode-file://vscode-app/{安装路径}/xxxx

之前写过一个自用命令,你可以参考下。

[Command]
Name=记录来源信息
Command="
    copyq:
    const MIME_TAGS = 'application/x-copyq-tags';

    const getClipStr = (mime, limit) => {
      const bytes = clipboard(mime);
      if (!bytes?.length) return null;
      // 仅读取头部
      return str(limit && bytes.length > limit ? bytes.mid(0, limit) : bytes);
    };

    const getDataStr = (mime) => {
      const val = data(mime);
      return val?.length ? str(val) : null;
    };

    const handlers = [
      {
        rawMime: 'CopyQ/copy-time',
        extract: () => dateString('yy-MM-dd hh:mm:ss'),
        tag: (time) => time,
      },
      {
        rawMime: 'CopyQ/source-url',
        extract: () => {
          return (
            // 移除末尾的终止符
            getClipStr('text/x-moz-url-priv')?.slice(0, -1) ??
            getClipStr('HTML Format', 2000)
              ?.match(/^SourceURL:\\\\s*([^\\\\r\\\\n]+)/m)?.[1]
              ?.trim()
          );
        },
        tag: (urlStr) => new URL(urlStr).hostname,
      },
      {
        rawMime: 'CopyQ/window-title',
        extract: () => getDataStr(mimeWindowTitle),
        tag: (text) => text?.trim(),
      },
    ];

    {
      const newTags = [];

      for (const handler of handlers) {
        const content = handler.extract();
        if (!content) continue;

        if (handler.rawMime) {
          setData(handler.rawMime, content);
        }

        // 仅在 tag 函数返回数据时添加
        const tagVal = handler.tag?.(content);
        if (tagVal) {
          newTags.push(String(tagVal));
        }
      }

      if (newTags.length > 0) {
        // 防止原始数据带有分隔标记用的英文逗号
        const safeTags = newTags.map((t) =>
          t.replace(/,/g, ',')
        );
        setData(MIME_TAGS, safeTags.join(', '));
      }
    }
    "
Automatic=true
Icon=

不过现在的问题不是获取数据,是保存数据。

CopyQ 调用 setData 时历史条目也会被写入相同数据,我上个月提了 issue,作者一直没回 :joy: