编程接口

目录

准备工作

0)版本检查

请检查 MaoXian 的版本,必须大于 0.4.7 才行。

1)启用 API

请到 设置页面 > 高级 进行启用

:MaoXian 在网页加载完成后,默认是不会加载 MaoXian 扩展的脚本的,而是需要等到用户主动触发裁剪动作,才开始加载脚本并运行。所以当你需要主动触发 MaoXian 时(如:在网页加载完成后,立即调用 MaoXian 进行裁剪),则需要启用「网页加载完成时即运行脚本」选项,否则 MaoXian 不能收到你的请求。

2)选择 js 代码的运行方式

方式一很方便,你需要安装一个可以运行油猴脚本的扩展,常见的有 Greasemonkey、 Tampermonkey, 选一个适用你浏览器的安装即可。然后编写「油猴脚本」,该方式需要你对「油猴脚本」有所了解。

当然,你也可选择方式二,编写浏览器扩展可以给你更大的可控性。

了解 MaoXian 的裁剪过程

MaoXian 的整个流程可大致分为三个阶段,如下:

  1. 准备阶段,此阶段,我们对网页内容进行调整(如:删除无关元素,选用高清图片……),确定要裁剪的元素(选择裁区),确定归类和标签(表单录入)。
  2. 裁剪阶段,此阶段,MaoXian 根据输入并结合配置信息,对选中的元素进行裁剪,并生成裁剪结果。
  3. 存储阶段,此阶段,MaoXian 对上一阶段生成的裁剪结果,进行保存(包含外部资源文件的下载,如:图片)。

本页面提供的接口,主要是用于「准备阶段」和「存储阶段」的。

我能用这些 API 做些什么?

准备阶段的应用举例

  1. 虽然 MaoXian 扩展已内置了 「MaoXian 助手」,但「MaoXian 助手」只能针对较普遍的一些操作。对于那些难搞的网页,可以通过这里的接口,对网页内容进行处理。
  2. 做标注,你可以在此阶段,对目标文本进行高亮,划下划线,注解等。
  3. 实现某种程度的自动裁剪。
  4. 可以使用你自定义的表单,而非默认的表单。

当然除了上方提到的例子,肯定还有许多其他的需求,发挥你的想象力 :)

存储阶段的应用举例

  1. 对「裁剪结果」做进一步的处理,通常是一些小的调整。
  2. 转存「裁剪结果」。把「裁剪结果」转存到其他笔记软件,或是知识管理软件。
  3. 把「裁剪结果」存到自己开发的知识管理软件。
  4. 甚至把「裁剪结果」处理成单文件格式,如:zip,pdf。

到了存储阶段,其实 MaoXian 的工作已经做完了,你拿到了「裁剪结果」,你想怎么处理就怎么处理 :P

MaoXian 的状态流程图

---> ready
       |
   +-----> actived* -->  selecting --> selected --> confirmed* --> clipping --> clipped* --> saving --> completed
   |          |              |             |            |                                                  |
 idle <----------------------+-------------+------------+--------------------------------------------------+

上方的图,箭头为状态的转变方向,带星号(*)的状态,为“可让出“状态。当一个状态被设置为“让出“时,MaoXian 会在这些状态事件发生后,停下来,等待对方的回应。

各事件概述如下:

事件名 带消息? 简介 备注
mx-wc.ready 初始化完成 注意:该事件会发出多次,详情见下文
mx-wc.actived 活跃(激活)状态 点击裁剪按钮后,在加载「用户界面(UI)」之前触发
mx-wc.selecting 进入自由选择模式 扩展激活后,便会进入自由选择模式,触发该事件
mx-wc.selected 选中某个选区 点击选中某个区域后,发出该事件
mx-wc.confirmed 确认某个选区 在选中区域后,按 Enter 键,发出该事件
mx-wc.clipping 开始裁剪 填写完表单后,点击保存后,发出该事件
mx-wc.clipped 裁剪完成 裁剪完成时,发出该事件
mx-wc.saving 存储中 存储操作开始时,发出该事件
mx-wc.completed 存储完成 存储完成后,发出该事件,至此,整个流程结束
mx-wc.idle 切回空闲状态 由其他活跃状态,进行退出或取消操作后,发出该事件

与 MaoXian 交互

我们是通过事件与 MaoXian 进行交互的。 MaoXian 会在到达某个状态时,发出对应的事件。另外 MaoXian 也会监听某些事件(你发送出的事件)。

监听 MaoXian 发出的事件

监听事件的工具函数:

function listenMxEvent(evName, listener) {
  document.addEventListener(evName, function(e) {
    // Note that some events may contain data(message)
    const msg = JSON.parse(e.detail || '{}');
    listener(msg);
  })
}

使用样例:

listenMxEvent('mx-wc.actived', function(msg) {
  // MaoXian is actived
  // Do your work
});

发送事件给 MaoXian

发送事件的工具函数:

function sendMxEvent(evName, msg) {
  // 1. create the event (We turn message to JSON string)
  const detail = JSON.stringify(msg || {});
  const ev = new CustomEvent(evName, {detail: detail});

  // 2. send the event
  document.dispatchEvent(ev);
}

注意: 发送事件与监听事件不同,发送事件必须等到 MaoXian 初始化完成之后,MaoXian 才能收到你发出的事件。即:须等到 MaoXian 的状态变为 ready 之后。

大部分情况下,你都不需要和 mx-wc.ready 事件打交道。都是先监听其他事件的发生后,再发送出事件,比如我们要预先设置保存表单里面的值:

listenMxEvent('mx-wc.actived', function(msg) {
  const msg = {formInputs: {category: 'box/news', tags: 'news'}};
  sendMxEvent('mx-wc.set-form-inputs', msg);
});

如果你需要在 MaoXian 处于 ready 状态时就发出某个事件,则需要注意点。MaoXian 提供了 mx-wc.ready 事件,以及一个挂在 window 对象下的属性 ___mxwc_is_ready___ (它的值为 true 或者 undefined) 来处理双方代码运行时机不可知这个问题。请看下方例子:

function sendEventWhenMaoXianIsReady() {
  if (window.___mxwc_is_ready___) {
    // send your maoxian event here
  } else {
    const readyEventListener = function() {
      document.removeEventListener('mx-wc.ready', readyEventListener);
      // send your maoxian event here
    }
    document.addEventListener('mx-wc.ready', readyEventListener);
  }
}

使用工具库调用 API

为了方便,我们把上方提到的工具函数合成一个工具库。使用这个工具库可以更方便地与 MaoXian 交互。如下:

该库支持你省略掉事件名的前缀,如监听事件:

MxAPI.listenEvent('actived', function(msg) {
  // MaoXian is actived
  // Do your work
});

该库对发送事件做了封装,如果当前 MaoXian 还没有 ready,则会把事件缓存下来,等到 MaoXian 变为 ready 时,再发送。所以发送事件就不需要考虑 MaoXian 是否已经初始化完成了,如下例:

MxAPI.sendEvent('mx-wc.clip-elem', {
  qType: 'css',
  q: 'article'
});
工具库源码(点我查看)

(function(root, factory) {

  root.MxAPI = factory();

})(window, function() {

  const EV_PREFIX = 'mx-wc.';
  const MX_PROPERTY = '___mxwc_is_ready___';
  const eventsToSend = [];
  const state = {ready: false};

  function listenEvent(evName, listener) {
    document.addEventListener(
      addNamespace(evName),
      wrapListener(listener)
    );
  }

  function sendEvent(evName, msg) {
    if (state.ready) {
      // Stringify the message
      const detail = JSON.stringify(msg || {});
      const ev = new CustomEvent(
        addNamespace(evName),
        {detail: detail}
      );
      document.dispatchEvent(ev);
    } else {
      eventsToSend.push({evName, msg})
    }
  }


  function wrapListener(listener) {
    return function(e) {
      // handle event message (JSON string)
      const msg = JSON.parse(e.detail || '{}');
      listener(msg);
    }
  }


  function addNamespace(evName) {
    return evName.startsWith(EV_PREFIX) ? evName : EV_PREFIX + evName;
  }

  function init() {
    state.ready = window[MX_PROPERTY] || false;
    if (!state.ready) {
      const readyEventListener = function() {
        state.ready = true;
        document.removeEventListener('mx-wc.ready', readyEventListener);
        while(eventsToSend.length > 0) {
          const {evName, msg} = eventsToSend.shift();
          sendEvent(evName, msg);
        }
      }
      document.addEventListener('mx-wc.ready', readyEventListener);
    }
  }

  init();

  return {listenEvent, sendEvent}

});

MaoXian 发出的事件

事件:mx-wc.ready

当 MaoXian 初始化完成时, 触发该事件。为了避免因代码运行顺序不同,而导致事件丢失,该事件会发出多次,我们在监听该事件时,需要避免多次执行。该事件须和 window.___mxwc_is_ready___ 一同使用,请看前一章节的示例代码。


事件: mx-wc.selecting

当进入「自由选择」模式时,就会触发该事件,如:


事件: mx-wc.selected

当进入「选中模式」时,触发该事件,也就是你点击某个选区后,就会触发。注意的是该事件不代表用户选择的裁剪区域,也可能是用户想删除的区域,所以不建议监听此事件。


事件: mx-wc.confirmed

从「选中模式」按下 Enter 后,会触发该事件,该事件带有消息。

消息结构如下:

{
  "elem": {
    "selector": ".mx-wc-confirmed-elem"
  }
}

消息表示,当前确认的裁区元素,其中的 selector 为 CSS 选择器。


事件: mx-wc.clipping

点击表单的保存按钮后,开始裁剪的时候会触发该事件。


事件: mx-wc.clipped

在裁剪结束时候,会发出该事件,该事件带有消息。

消息结构如下:

{
  "clipping": {
    "info": {
      "version" : "2.0",
      "clipID": "612905100",
      "format": "html",
      "title": "a-awesome-title",
      "link": "https://example.org/post/awesome.html",
      "category": "box/security",
      "tags": ["tagA", tagB"],
      "created_at": "1989-06-04 03:25:00"
    },
    "tasks": [
      {
        "taskType": "mainFileTask",
        "type": "text",
        "filename": "mx-wc/box/security/a-awesome-title/index.html",
        "mimeType": "text/html",
        "text": "<html>...</html>",
        "clipId": "612905100",
        "createdMs": "612905100999",
      }
    ]
  }
}

其中,info 为本次裁剪的一些基本信息,tasks 为本次裁剪生成的待存储的任务。

其中 task 的各属性描述如下:

属性名 说明 备注
taskType 任务类型 目前有 mainFileTask, imageFileTask, styleFileTask, fontFileTask, frameFileTask, infoFileTask 以及 titleFileTask
type 该资源的内容类型 可选值为 url 或者 text
filename 存储时使用的文件名 -
mimeType 资源的 mimeType type 为 text 才有该属性
text 该资源的文本内容 type 为 text 才有该属性
url 该资源的 url type 为 url 才有该属性
headers HTTP 头部 type 为 url 才有该属性
timeout HTTP 请求的超时时长 type 为 url 才有该属性
clipId 本次裁剪的 ID -
createdMs 本次裁剪创建的时间 字符串,单位是毫秒

如果你要存储这些 task,那么对于 type 为 text 的 task,则直接存储即可,而对于 type 为 url 的 task,你需要通过它的 url 先把对应的资源下载下来,再进行存储。


事件: mx-wc.completed

整个裁剪流程完成时,触发该事件,该事件带有消息。

消息结构如下:

{
  "clipID": "612905100",
  "filename": "/home/user/Downloads/clippings/box/security/253143434/index.html",
  "url": "file:///home/user/Downloads/mx-wc/box/security/a-awesome-title/index.html",
  "originalUrl": "https://a.org/posts/awesome.html",
  "completedAt": '2000-01-01 00:00:00'
}

事件: mx-wc.idle

注意:在 mx-wc.ready 过后,并不会触发 mx-wc.idle 事件。该事件只在其他活跃状态下,进行退出或取消后,才会触发,如下:

一般通过监听该事件,做一些撤销或收尾的工作。

MaoXian 监听的事件

事件: mx-wc.set-form-inputs

该事件用于预设置表单的输入值,MaoXian 会在显示表单的时候,自动帮你输入这些预设的值。一般我们都会在监听到 mx-wc.activedmx-wc.selecting 事件后,发出该事件。

消息结构如下:

{
  "formInputs": {
    "category": "box/it",
    "tagstr": "security,privacy,freedom"
  }
}

formInputs 为表单的输入项,四项都为选填,名字和解释如下:

名字 说明 默认值
format 存储格式,只能为 htmlmd 取决于你的设置(见扩展设置页面)
title 对应表单的标题 当前网页的标题
category 对应表单的分类(多级分类用 / 隔开) 取决于你的设置(见扩展设置页面)
tagstr 对应表单的标签(多个标签用 ,空格 隔开)

事件: mx-wc.set-form-options

该事件用于预先设置表单输入项的可选值,这些可选词会被用于自动补全。一般我们都会在监听到 mx-wc.activedmx-wc.selecting 事件后,发出该事件。

消息结构如下:

{
  "formOptions": {
    "categories": ["news", "hobby", "tools/desktop", "tools/mobile"],
    "tags": ["security", "privacy", "freedom"]
  }
}

formOptions 为表单输入项的可选值,下方列出的都为选填,名字和解释如下:

名字 类型 说明 默认值
titles Array 对应表单的标题 当前网页的可能是标题的文字
categories Array 对应表单的分类(多级分类用 / 隔开) 扩展存储的分类集合
tags Array 对应表单的标签 扩展存储的标签集合

注: 一般都不需要提供 titles,MaoXian 默认会从当前网页上查找可能是标题的文字,并作为可选项,这能满足绝大部分需求,如果某些网页太特殊,则考虑用『助手』功能去处理。

事件: mx-wc.select-elem

该事件用于选择某个元素,相当于你点击了某个元素。 一般我们会在监听到 mx-wc.selecting 事件后,发送出该事件。

消息结构如下:

{
  "qType": "css",
  "q": "#article"
}

事件: mx-wc.confirm-elem

该事件用于选择某个元素,并且做了确认(直接到达输入表单信息那一步)。一般我们会在监听到 mx-wc.selecting 事件后,发送出该事件。

消息结构如下:

{
  "qType": "css",
  "q": "#article"
  "formInputs": {
    "category": "box/it",
    "tagstr": "security,privacy,freedom"
  }
}

:该事件消息中的 formInputs 会比 mx-wc.set-form-inputs 具有更高的优先级。


事件: mx-wc.clip-elem

该事件用于选中某个元素,并立即对其进行裁剪。

消息结构如下:

{
  "qType": "css",
  "q": "#article"
  "formInputs": {
    "category": "box/it",
    "tagstr": "security,privacy,freedom"
  }
}

:该事件消息中的 formInputs 会比 mx-wc.set-form-inputs 具有更高的优先级。


事件: mx-wc.overwrite-config

该事件用于重写某些配置项,并且重写的结果只在本次裁剪有效。一般在监听到 mx-wc.actived 后,可发出该事件。

消息结构如下:

{
  "config": {
    "rootFolder": "clippings",
    "defaultCategory": "misc"
    ...
  }
}

当前允许重写的配置项如下,所有可配置项均为选填。注: 其中的默认值指的是 MaoXian 扩展提供的默认值,该值只作为参考,实际上使用的是你自己配置页面上的值。

存储相关

可在扩展的 扩展 > 设置页面 > 存储设置 一节找到可使用的变量及其说明。

名字 说明 类型 默认值
clippingHandler 处理程序 String Browser
saveFormat 保存格式 String html
rootFolder 根目录 String mx-wc
defaultCategory 默认分类 String default
clippingFolderName 裁剪目录 String $YYYY-$MM-$DD-$TIME-INTSEC
mainFileFolder 主文件的存储目录 String $CLIPPING-PATH
mainFileName 主文件的文件名 String index.$FORMAT
saveInfoFile 是否保存元信息文件 Boolean true
infoFileFolder 元信息文件的存储目录 String $CLIPPING-PATH
infoFileName 元信息文件的文件名 String index.json
saveTitleFile 是否保存标题文件 Boolean true
titleFileFolder 标题文件的存储目录 String $CLIPPINT-PATH
titleFileName 标题文件的文件名 String a-title_$TITLE
frameFileFolder 内嵌的网页文件的存储目录 String $CLIPPING-PATH/frames
frameFileName 内嵌的网页文件的文件名 String $TIME-INTSEC-$MD5URL.frame.html
assetFolder 资源文件的存储目录 String $CLIPPING-PATH/assets
assetFileName 资源文件的文件名 String $TIME-INTSEC-$MD5URL$EXT

备注

Markdown 文档相关

请参考 扩展 > 设置 > Markdown 的说明文字进行配置。

名字 说明 类型 默认值 可选值
markdownTemplate Markdown 模板 String \n{{content}}\n  
markdownOptionHeadingStyle 标题格式 String atx setextatx
markdownOptionHr 水平分割线 String * * * * * *- - - 等等
markdownOptionBulletListMarker 子弹列表的行头符 String * *+-
markdownOptionCodeBlockStyle 代码块格式 String fenced indentedfenced
markdownOptionFence 代码块分隔符 String ``` ```~~~
markdownOptionEmDelimiter 强调(斜体)分隔符 String _ _*
markdownOptionStrongDelimiter 加重(粗体)分隔符 String ** **__
markdownOptionLinkStyle 链接格式 String inlined inlinedreferenced
markdownOptionFormulaBlockWrapper 块状公式的格式 String padSameLine sameLine, padSameLIne, multipleLinemathCodeBlock

备注

HTML 文档相关

请参考 扩展 > 设置 > HTML 的说明文字进行配置。

名字 说明 类型 默认值 可选值
htmlSaveClippingInformation 追加裁剪信息到内容尾部 Boolean false falsetrue
htmlCustomBodyBgCssEnabled 允许自定义 body 标签的 CSS 背景颜色 Boolean false falsetrue
htmlCustomBodyBgCssValue body 标签的 CSS 背景颜色 String #000000 查看 background-color (CSS)
htmlCompressCss 压缩样式(CSS) Boolean false falsetrue
htmlCaptureImage 图片 String saveAll saveAllsaveCurrent
htmlCaptureAudio 声音 String remove saveAllsaveCurrentremove
htmlCaptureVideo 影片 String remove saveAllsaveCurrentremove
htmlCaptureApplet Applets String remove saveAllremove
htmlCaptureEmbed Embeds String saveImage saveAllsaveImageremovefilter
htmlCaptureObject Objects String saveImage saveAllsaveImageremovefilter
htmlCaptureIcon 网站图标 String remove saveAllsaveFaviconremove
htmlCaptureCssRules 样式规则 String saveUserd saveAllsaveUserd
htmlCaptureWebFont Web 字体 String remove saveAllremovefilterList
htmlCaptureCssImage 样式图片 String remove saveAllremove
htmlEmbedFilter Embeds 过滤器 String <images> -
htmlObjectFilter Objects 过滤器 String <images> -
htmlWebFontFilterList Web 字体过滤器组 String woff2|woff|otf|ttf -

Web 请求相关

请参考 扩展 > 设置 > 高级设置 的说明文字进行配置。

名字 说明 类型 默认值 可选值
requestTimeout 超时(秒) Integer 300 5 ~ 86400
requestMaxTries 最大尝试次数 Integer 3 大于1的整数
requestReferrerPolicy Referrer 请求头 String originWhenCrossOrigin noReferreroriginoriginWhenCrossOriginunsafeUrl

事件: mx-wc.set-yielding

该事件用于把某个状态设置为「让出」,目前可让出的状态有:activedconfirmedclipped

消息结构如下:

{
  name: 'actived'
}

警告,设置过后,通过 document.removeEventListener 是无法撤销的,请使用 mx-wc.unset-yielding 进行相关的撤销操作。

一般在下面的一些使用场景下,会设置对应的状态为让出。

另: 当本扩展已经把控制权让出给对接方时,其只会对特定的事件进行响应,如下:

让出点 只会响应以下事件
actived mx-wc.yield-backmx-wc.resume-actived
confirmed mx-wc.yield-back
clipped mx-wc.yield-backmx-wc.set-saving-hint

事件: mx-wc.unset-yielding

该事件用于撤销某个状态的「让出」。

消息结构如下:

{
  name: 'actived'
}

事件: mx-wc.yield-back

该事件用于让回控制权。即当你把一个状态设置为让出后,当到达这个状态时,本扩展会把控制权让出来,并等待你的回应。你执行完你的操作后,应该发出该事件把控制权让回给本扩展。

消息结构如下:

{
  "nextAction": {"name": "xxx", "msg": {}}
}

nextAction 是你让回控制权后,期望本扩展执行的动作。不同的让出点,允许执行的动作不同。如下:

当让出状态为 actived 时,让回时,允许的动作

{
  "nextAciton": {
    "name": "selecting"
  }
}

当让出状态为 confirmed 时,让回时,允许的动作

{
  "nextAction": {
    "name": "clipElem",
    "msg": {
      "qType": "css",
      "q": "#mx-wc-confirmed-elem",
      "formInputs": {
        "category": "box/it",
        "tagstr": "security,privacy,freedom"
      }
    }
  }
}

当让出状态为 clipped 时,让回时,允许的动作

{
  "nextAction": {
    "name": "saveClipping",
    "msg": {clipping: clipping}
  }
}
{
  "nextAction": {
    "name": "completeClipping",
    "msg": {
      "result": {
        "clipID": "612905100",
        "originalUrl": "https://a.org/posts/awesome.html",
        "filename": "/home/user/Downloads/clippings/box/security/253143434/index.html",
        "url": "https://my.server.org/clippings/,
        "downloadItemId": "",
        "taskNum": 6,
        "failedTaskNum": 0,
        "pendingTaskNum": 0,
        "completedTaskNum": 6,
        "failedTasks": []
      }
    }
  }
}

failedTask 的结构如下:

{
  "filename": "clippings/box/security/253143434/assets/a.jpg",
  "errMsg": "NetError: open timeout*
}


事件: mx-wc.resume-actived

该事件已过时,请使用 mx-wc.yield-back 来让回控制权。

如果你把 actived 状态设置为「让出」,则可以在执行完某些操作后,通过发送该事件,让 MaoXian 继续走下面的流程。发送该事件不需要带消息。


事件: mx-wc.set-saving-hint

该事件用于设置「存储阶段」的提示信息(如:存储进度信息),一般只有你把 clipped 状态设置为「让出」时,才会用到该事件。

消息结构如下:

{
  hint: 'saving...'
}

写在最后

该页面描述的 API 现还未很成熟(稳定),未来可能会有一些改动。若你在使用这些 API 的过程中遇到一些问题或是疑问,请反馈给我们,谢谢 ;)


首页