advanced-related-pages-2
外部projectを自分のprojectとみなしてリンク構造を計算するUserScript old version:
このscriptでやること
リンク情報の格納
リンク情報の更新
指定したページの逆リンクを取得
このscriptでやらないこと
リンク情報のfetch
link networkの計算方法
全て同じprojectのリンクだとして計算する
大文字小文字の違いは無視する
全角半角スペースとアンダーバーの違いも無視する
data構造
リンク情報
各ページのリンク先ページタイトルを入れておく
code:ts
interface LinkCache {
project: string,
title: string,
links: {
title: string,
}[];
}
逆リンク情報
各ページを参照しているページタイトルを保存する
LinkCacheから必要な分だけ計算する
計算処理が重いので、一度に計算するようなことはしない
参照元のproject nameは保持しておく
code:ts
interface BackLinksData {
title: string,
backLinks: {
project: string,
title: string,
}[];
}
code:script.js
export class RelatedPageManager {
constructor() {
this._worker = new Worker('/api/code/takker/advanced-related-pages-2/link-calc-worker.js');
}
リンク情報の追加と削除
code:script.js
push(...linkCache) {
this._worker.postMessage({type: 'push', linkCache: linkCache});
}
clear() {
this._worker.postMessage({type: 'clear'});
}
指定したページの逆リンク情報を取得する
既にbackLinksDataにあればそれを返す
なければ計算して返す
code:script.js
async getBackLinks(title) {
// workerに処理を委託して待つ
const result = new Promise((resolve, reject) =>
this._worker.addEventListener('message', message => {
resolve(message.data);
}, {once: true}));
this._worker.postMessage({type: 'get', title: title});
return await result;
}
// debug用
_log(msg, ...objects) {
console.log([RelatedPageManager] ${msg}, objects);
}
}
WebWorkerのコード
やること
データの格納
大文字小文字の変換とスペースをタブにする変換を行っておく
逆リンクの計算
code:link-calc-worker.js
let linkCache = [];
let backLinksData = [];
self.addEventListener('message', async message => {
switch (message.data.type) {
case 'push':
push(...message.data.linkCache);
break;
case 'clear':
clear();
break;
case 'get':
self.postMessage(getBackLinks(message.data.title));
break;
}
});
function push(...links) {
// 文字列の変換
const format = title => title.toLowerCase().replace(/\s/g,'_');
const temp = links.map(data => {
return {
project: data.project,
title: format(data.title),
links: data.links
.map(link => format(link)),
};});
linkCache.push(...temp);
backLinksData = [];
_log(Pushed link cache: %o,linkCache);
}
function clear() {
linkCache = [];
backLinksData = [];
}
function getBackLinks(title) {
// 計算済みの逆リンク情報があればそれを返す
const backLinksCache = backLinksData.find(data => data.title === title)?.backLinks;
if (backLinksCache) return backLinksCache;
// なければ新たに計算し直す
_log('Start calculating back links...')
const backLinks = linkCache
.flatMap(cache => cache.links.includes(title) ?
_log(Finish calculating ${backLinks.length} back links.);
return {
title: title,
backLinks: backLinks,
};
}
// debug用
function _log(msg, ...objects) {
if (objects.length === 0) {
console.log([link-calc-worker] ${msg});
return;
}
console.log([link-calc-worker] ${msg} %o, ...objects);
}