Clipyをnode.jsで触るライブラリを作りました


@econa77さんが2015年リリースしたクリップボード拡張Macアプリ「Clipy」はこの2年間世界中の人気を集まりました。昨年、とあるIssueと格闘している間、Clipyの中身を少しのぞきました。そこで得られた知見でこの Clipy Mate プロジェクトをはじめました。

GitHubレポジトリ

システム要項

  • MacOS 10.10 and over
  • Clipy v1.2.0 and over
  • Node.js v8.9.0 ~ v10 (Realmはnode v12には対応していません)

API

インストール

npm i clipy-mate-core

Import

ES6

const ClipyMate = require('clipy-mate-core');
const clipy = new ClipyMate();

TypeScript

import ClipyMate from 'clipy-mate-core'
const clipy: ClipyMate = new ClipyMate();

全スニペットの取得

// Read all Folders and Snippets
clipy.readSnippets().then((folders) => {
  console.log(folders);
  console.log(folders[0].snippets);
});

ClipyがエクスポートしたXMLファイルをParse

// Parse `snippet.xml`
const fs = require('fs');
clipy.parseXml(fs.readFileSync('./snippet.xml')).then((folders) => {
  console.log(folders);
  console.log(folders[0].snippets);
});

フォルダとスニペットの作成

フォルダの作成

// Create or Update a folder
// it will update a folder has same `identifier` field
// or create a new folder if `identifier` is blank or not found
clipy.upsertFolder({ title: 'test folder' }).then(folder => {
  console.log(folder.identifier);
});

スニペットの作成(フォルダ指定要)

// Create or Update a snippet inside a folder
// it will update a snippet has same `identifier` field
// or create a new snippet if `identifier` is blank or not found
const folder = clipy.CPYFolder[0];
const folderId = folder.identifier;
clipy.upsertSnippet({ title: 'test snippet', content: 'test' }, folderId).then(snippet => {
  console.log(snippet.identifier);
});

削除

フォルダ(と配下のスニペット)の削除

// Destroy a specific folder (All snippets in this folder will also be destroyed)
const folder = clipy.CPYFolder[0];
const folderId = folder.identifier;
clipy.destroyFolder(snippetId).then(folder => {
  console.log(folder);
});

スニペットの削除

// Destroy a specific snippet
const snippet = clipy.CPYSnippet[0];
const snippetId = snippet.identifier;
clipy.destroySnippet(snippetId).then(snippet => {
  console.log(snippet);
});

全てを削除

// [Danger!] Destroy all folders and snippets
clipy.clearAllSnippets().then();

Realm Connectionの解除

// After all
clipy.disconnect();

ロードマップ

  • コアライブラリ: clipy-mate-core [v1.0.3]
  • コンソルアプリ: clipy-mate-cli [v0.2.1]
  • VS Code プラグイン: clipy-mate-vscode [WIP]

原理

ClipyはRealmというデータベースを使ってスニペットを管理しています。
該当データベースは下記の場所にストックされていることもわかりました。

$HOME/Library/Application Support/com.clipy-app.Clipy/default.realm

Realm Browserでこの default.realm を開くと、データ構造が確認できます。

既知のBug等

  • Clipy v1.1.2以下を使う場合、Clipyが起動している間、default.realmの操作はできないため、必ずClipyを終了してから操作を行います。Clipy v1.2.0以上であれば、そんな問題が存在しません。
  • スニペットを更新した場合、Clipyを再起動しないと「スニペットを編集」で反映されない問題があります。
  • Clipyのデータを読み取るためのライブラリRealmは、nodejs v12に対応していないため、node v10系がおすすめです。参考

参考

クリップボード拡張Macアプリ「Clipy」を公開しました