external-completion-3/source
dependencies
code:script.js
import {SearchEngine} from '../advanced-link-searcher/script.js';
import {scrapboxDOM} from '../scrapbox-dom-accessor/script.js';
import {getIndex} from '../scrapbox-char-accessor-2/script.js';
export const setting = (projects, {
trigger = /^\[\//,
makeRaw = (text) => text.slice(2, -1),
icon = false,
timeout = 3000,
limit = 30,
verbose = false,
} = {}) => {
const engine = new SearchEngine(projects.filter(project => project !== scrapbox.Project.name), {icon, verbose});
const test = ({char}) => {
const link = char?.closest?.('.page-link');
if (!link) return false;
if(!trigger.test(link.innerText)) return false;
return link;
};
const getLink = ({char}) => {
const link = test({char});
if (!link) return;
// 座標や文字列を計算する
return {
target: makeRaw(link.innerText),
index: getIndex(link),
length: link.innerText.length,
position: adjustFirstCharPos(link),
};
};
return {
test,
display: (...params) => getLink(...params)?.target,
onchange: async (pos, replace) => {
const link = getLink(pos);
if (!link) return;
const {target, index, length, position} = link;
console.log([external] search query "${target}");
const {result} = await engine.search(target, {timeout, limit});
console.log([external] finish:, result);
if (!result) return;
return {
position,
items: result?.map?.(path => ({
title: path,
link: path,
...(icon ? {image: /api/pages${path}/icon} : {}),
onClick: ({mode} = {}) => {
mode = mode ?? 'default';
.find(action => mode === action.mode) ?? {};
command?.(path, replace, index, length);
return;
},
})),
};
},
};
};
const openWindow = {
mode: 'newTab',
command: path => window.open(https://scrapbox.io${path}),
};
const writeIcon = {
mode: 'icon',
command: (path, replace, index, length) => replace([${path}.icon], index, length),
};
const writeLink = {
mode: 'default',
command: (path, replace, index, length) => replace([${path}], index, length),
};
const writeBareLink = {
mode: 'bare',
command: (path, replace, index, length) => replace([${path.match(/^\/[\w\-]+\/(.+)$/)[1]}], index, length),
};
const adjustFirstCharPos = (dom) => {
// リンクの先頭文字に補完windowの位置を合わせる
const editorRect = scrapboxDOM.editor.getBoundingClientRect();
const {left, bottom} = dom.getBoundingClientRect();
return {
top: bottom - editorRect.top,
left: left - editorRect.left,
};
};