scrapbox-char-accessor
追加したい機能
非空白文字を除いた先頭/末尾判定
(やれたらやる) 文字の種類
リンク
画像
コードブロック
etc.
依存
code:script.js
import {line as l} from '/api/code/programming-notes/scrapbox-line-accessor/script.js';
class Char {
行idと文字番号を保持する
行idなら、アウトライン編集で行を入れ替えても追跡できる
code:script.js
constructor({id, index}) {
this._id = id;
if (!this.lineDOM) throw Error(#L${id} is an invalid line id.);
this._index = index;
}
提供する機能
文字の列番号
code:script.js
get index() {
return this._index;
}
中身の文字
表示上の文字ではなく、テキストとして記録されている方の文字を取得する
code:script.js
get text() {
return scrapbox.Page.lines.find(line => line.id === this._id)
}
文字がある行
code:script.js
get line() {
return l(this.lineDOM);
}
行の先頭の文字か
code:script.js
get isHead() {
return this.index === 0;
}
行の末尾の文字か
code:script.js
get isEnd() {
return this.text === '' || this.index === this.text.length - 1;
}
前の文字
code:script.js
get next() {
if (this.isHead) return undefined;
return new Char({id: this._id, index: this.index - 1});
}
後ろの文字
code:script.js
get prev() {
if (this.isEnd) return undefined;
return new Char({id: this._id, index: this.index + 1});
}
(WIP)文字を囲むリンクを取得する
内部リンクと外部リンクのどちらかを取得する
2021-01-15 14:12:18 一応できたけど、設計が微妙だなtakker.icon
code:script.js
get link() {
const livingLink = this.DOM.closest('a');
if (livingLink) {
const index = parseInt(livingLink
.querySelector(charSelector).classList0.slice(2)); return {
type: livingLink.type,
href: livingLink.href,
text: livingLink.type === 'link' ? livingLink.textContent.slice(1, -1) :
livingLink.textContent.slice(1),
index,
DOM: livingLink,
}
}
// 記法がむき出しになり、リンクとしての機能を果たしていない外部リンク
// URLしかないリンクだとバグる
const deadLink = this.DOM.closest('span.link');
if (deadLink) {
return {
type: 'link',
href,
text,
}
}
return undefined;
}
DOMへのアクセス
基本は内部関数用
外部からはどうしても必要なときだけ使う
scrapboxのeditor構造に破壊的な変更が加わると使えなくなる恐れがある
文字のいる行のDOM
code:script.js
get lineDOM() {
return document.getElementById(L${this._id});
}
文字のDOM
code:script.js
get DOM() {
return this.lineDOM?.getElementsByClassName(c-${this._index})?.0; }
code:script.js
}
外部公開用
文字のDOM, 行番号&文字番号, 行id&文字番号のいずれかで作成する
code:script.js
const linesDOM = document.getElementsByClassName('lines')?.0; export const char = (value1, value2) => {
// 文字のDOMのとき
return new Char({
id: value1.closest('div.line').id.slice(1),
index: parseInt(value1.classList0.replace(/c-(\d+)/,'$1')), });
}
// 行id&文字番号のとき
if ((typeof value1) === 'string') {
if ((typeof value2) !== 'number') return undefined;
const id = /^Labcdef\d+$/.test(value1) ? value1.slice(1) : value1; return new Char({id, index: value2});
}
// 行番号&文字番号のとき
if ((typeof value1) === 'number') {
const id = scrapbox.Page.linesvalue1.id; if (!id || (typeof value2) !== 'number') return undefined;
return new Char({id, index: value2});
}
return undefined;
}