StringObserver
変更があったときのみ入力候補を更新する
更新とか
2020-09-01 09:24:28
サロゲートペアに対応した?対応できなかった
2020-08-26 23:51:28 入力補完対象の文字列を探すのに使う正規表現を外から指定できるようにした
クラス名を変えた
既知の問題
🔳
を含む行だと判定処理に失敗する
matchAll
がサロゲートペアを含んだ文字列の文字数を計算できないのが原因
script.js constructor(editor, {regex = /\[\/[^\s!"#%&'()\*\+,\-\.\/\{\|\}<>_~\]][^\]]*\]/ug,
makeRaw = string => string.substr(2, string.length - 3)}
= {}) {
this.raw = undefined; // 監視対象の文字列
this.target = undefined; // 加工した文字列
this.editor = editor;
this.regex = regex;
this.makeRaw = makeRaw;
}
// 監視を更新する
reload(cursor) {
// focusがcursorになかったら何もしない
if(editor.getElementsByClassName('cursor-line').length == 0) return false;
const oldRaw = this.raw
this.raw = this._getLinkIncludingCursor(cursor);
this.target = this.raw ? this.makeRaw(this.raw) : undefined;
return oldRaw !== this.raw ;
}
// cursorを含む外部projectへのリンクを取得する関数
_getLinkIncludingCursor(cursor){
const cursorLine = editor
.getElementsByClassName('cursor-line')[0];
if(!cursorLine) return undefined;
// cursorのいる行から正規表現にマッチする文字列の情報を全て取り出す
const matchedWords = [...cursorLine.textContent.matchAll(this.regex)];
座標取得は少し工夫が必要
対策
script.js // 要素の左端の相対座標を取得する
const getLeftPosition = targetElement => targetElement.getBoundingClientRect().left - cursorLine.getBoundingClientRect().left;
// cursorを含む文字列のみ抽出
const targetWord = matchedWords
// cursorを含む外部projectリンクは一つしかないはずなので、filterではなくfindを使う
.find(match => {
//console.log(`matched ${match[0]}, index: ${match.index}`);
const start = cursorLine
.getElementsByClassName(`c-${match.index}`)[0];
const end = cursorLine
.getElementsByClassName(`c-${match.index + match[0].length -1}`)[0];
// '['の右端の座標
const startLeft = getLeftPosition(start);
// ']'の左端の座標
const endLeft = getLeftPosition(end);
// cursorの左端の座標
const cursorLeft = parseInt(cursor.style.left);
return startLeft <= cursorLeft && cursorLeft <= endLeft;
});
return targetWord?.[0];
}
}