插件是 Steward 的核心功能,通过插件可以快捷地完成大部分日常浏览器操作。

Steward 自带一系列插件,同时也开放了插件 api,只需要几行代码你就能完成自己想要的插件的开发。

自带插件

Steward 自带插件可以分为以下4类

  • 浏览器插件 -- 对浏览器功能的便捷化以及增强,如书签、历史记录等
  • 扩展类插件 -- 通过 Steward 操控其它浏览器插件,如单词小卡片
  • Steward 插件 -- 通过插件完成 Steward 本身功能的管理,如 NewTab、Wallpaper 等
  • 其它插件 -- 与浏览器无关的插件,如 URL Block、Pocket 查询、TODOList 等等

插件开发

从 V3.5.1 以后,Steward 开放了 api,并提供了 plugin 编辑器。

数据结构

  • steward 对象

代码包裹在 module.exports = function(steward) {} 中,steward 为注入的 api

{
    mode, // steward application mode: 'newTab' | 'popup' | 'content'
    config, // user config
    data, // steward data: { page: Object }
    chrome, // chrome api
    util, // 工具 api
    dayjs, // 日期库
    $, // jquery
    axios, // http 库
    constant, // 常量,
    storage, // chrome.storage 的 promise 封装
    browser // https://github.com/mozilla/webextension-polyfill
}
  • plugin 组成结构
{
    author, // 开发者 id,比如邮箱或 github 账号
    version, // 版本号
    name, // 插件名,与 author 一起组成唯一识别 id(uid)
    category: 'other', // 插件类别,填 ‘other’ 就好,暂时没用
    icon, // 插件 icon
    title, // 插件标题
    commands, // 插件命令列表,可以为空,为空时插件类型为 search
    onInput, // 核心 api, 输入事件函数
    onEnter // 核心 api,选中事件函数
}

  • command 数据结构
{
    // command
    key, // { String } command 的 trigger
    type, // { String } command 的类型,枚举值,包含['always', 'regexp', 'keyword', 'other', 'search']
        // 对应不同的查询类型及阶段,通常填 `keyword` 就好
    title, // { String } command 的标题
    subtitle, // { String } command 的副标题/描述
    icon // { String } command 的图标 url
}
  • 查询结果 item 数据结构
{
    // item
    key, // { String} 条目类型`CONSTANT.BASE.ITEM_TYPE`,枚举值有['plugins', 'url', 'copy', 'action', 'app']
        // 为 plugins 时,将 item.id 作为新的命令应用
        // 为 url 时,在新标签页打开 item.url
        // 为 copy 时,将 item.title 拷贝到剪贴板
        // 为 action 时,emit 'action' 事件,通常由页面模式的 website 接收处理,此处文档待完善
        // 为 app 时,emit ''app:handle' 事件,比如 'Backup' 备份
    universal, // { Boolean } 是否为通用条目,为 true 时,onEnter 将由 Steward 根据item.key 值处理
    icon, // { String } 条目图标 url,通常与 plugin / commands 图标相同
    title, // { String } 条目标题
    desc // { String } 条目副标题/描述
}

函数方法

plugin

  • onInput

核心 api,用户输入 trigger + space 后触发

  /**
  * @param { String } query 用户输入的字符串,比如输入框中为 `ip 192.168.1.1`,那么 `query` 就是 `192.168.1.1`
  * @param { Object } command 用户当前触发的命令,由于 plugin 支持多 commands,因此可用此参数来具体识别
  * @return { Promise[Array] | Array } 查询结果,支持 Promise 以及普通 Array 数组
  */
  function onInput(query, command) {
      return Promise.resolve([Array[Item]]);
  }
  • onEnter

核心 api,用户按 Enter/Return 键或点击某条查询结果时调用

  /**
  * @param { Object } item 选中的查询结果条目
  * @param { Object } command 当前触发的命令
  * @param { String } query 当前的查询字符串
  * @param { Boolean } shiftKey 用户是否同时按下 shift 键
  * @param { Array } list 全部的查询结果
  * @return { Promise[String | Boolean]}
  *           Promise[String] 作为新的命令被应用到输入框中
  *           Promise[Boolean] 只对页面模式有效,在Boolean 为 false 时,Steward 弹框将延迟关闭
  */
  function onEnter(item, command, query, shiftKey, list) {
      return Promise.resolve([String | Boolean]);
  }

steward.util

  • getDefaultResult
/**
* 根据 command 生成默认查询结果
* @param { Object } command 在 plugin 里定义的 command
* @return { Array[Item] } 包含一条对 onEnter 透明的默认查询结果
*/
function getDefaultResult(command) {
}
  • getEmptyResult
/**
* 根据 command 生成默认空查询结果
* @param { Object } command 在 plugin 里定义的 command
* @param { String | Optional } msg 空查询提示
* @return { Array[Item] } 包含一条对 onEnter 透明的默认空查询结果
*/
function getEmptyResult(command, msg) {
}
  • copyToClipboard
/**
* 将 text 拷贝到剪贴板
* @param { String } text 将要拷贝的文本
* @param { Boolean } showMsg 是否弹出提示
* @return
*/
function copyToClipboard(text, showMsg) {
}
  • getParameterByName
/**
* @param { String } name param name
* @param { String } search 默认为 window.location.search
* @return { String } 
*/
function getParameterByName(name, search = window.location.search) {
}
  • toast -- https://github.com/CodeSeven/toastr

  • 其它

steward.axios -- http库

https://github.com/axios/axios

steward.$ -- jquery

steward.dayjs -- 日期库

https://github.com/iamkun/dayjs

steward.constant -- steward 内置常量

具体可以自行 console.log 查看

图示

示例

module.exports = function(steward) {
  const version = 1;
  const author = 'solobat';
  const name = 'IP Search';
  const key = 'ip';
  const type = 'keyword';
  const icon = 'http://static.oksteward.com/ip.png';
  const title = '查询 ip';
  const subtitle = '输入 ipv4 地址,查询 ip 所在地点及运营商';

  // commands 为命令的数组,支持多个命令
  const commands = [{
	  key,
	  type,
	  title,
	  subtitle,
	  icon
  }];
  
  //============== 插件逻辑 =============//
  const APP_KEY = 'xxxxx';
  const ipRegexp = /\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.|$)){4}\b/;
  
  function searchIp(ip) {
	const url = `http://apis.juhe.cn/ip/ip2addr?ip=${ip}&key=${APP_KEY}`;
   
	  return steward.axios.get(url);
  }
  
  function dataFormat(data) {
	  return [
        {
            key,
            universal,
            icon,
            title: `${data.area} -- ${data.location}`,
            desc: '按 Enter 复制到剪贴板'
        }
      ];
  }

  function onInput(query, command) {
	  const str = query.trim();
	
	  if (str && ipRegexp.test(str)) {
		  return searchIp(str).then(results => {
			const resp = results.data;
			
			  if (resp.resultcode == 200) {
			  return dataFormat(resp.result); 
			} else {
			  return [];
			}
		  }).catch(results => {
			  return steward.util.getDefaultResult(command);
		  });
	  } else {
		  return steward.util.getDefaultResult(command); 
	  }
  }
  
  function onEnter(item, command, query, shiftKey, list) {
	  steward.util.copyToClipboard(item.title, true);
  }
  
  return {
	  author,
	  version,
	  name,
	  category: 'other',
	  icon,
	  title,
	  commands,
	  onInput,
	  onEnter
  };
}

更多 plugin 示例

Steward 官方插件仓库