pin-diary-6 pull:1
タイトルを pin-diary-6 pull#1
から pin-diary-6 pull:1
へ変更
#
が入っているとハッシュタグを作成できなくなってしまうため
既にページが作成されて書き込みされていた場合にテンプレートフォーマットを挿入すると、空行より下が分断されてしまうバグ
これはおそらく、ページを書き込んだ際に機能する
空行承り太郎の空行を、テンプレートの一部として誤認してしまうのが原因
テンプレートが分断されていた場合は、固まったテンプレートを新たに挿入する形で解決しました
これ以外の解決策としては、テンプレートの一部が欠落していた場合、既存のテンプレート行(空行除く)に欠落しているテンプレートを追記する処理が考えられると思います
修正後のソースコード
6依存(未変更)
にカテゴライズされているソースファイル以外は書き換えてあります
修正ありがとうございます
返信遅れてすみません
お気になさらず
修正反映は少々お待ち下さい
やること
diff確認
$ curl https://scrapbox.io/api/code/villagepump/pin-diary-5/util.ts > util_old.ts && curl https://scrapbox.io/api/code/Mijinko-other/pin-diary-6-sd-dev_2022-12-04/util.ts > util.ts && diff -y util_old.ts util.ts
arrow functionに書き換え
依存関係の見直し
違うversionを参照しているとややこしい
今までのversionをgithubにサルページしておこうかな
前後に空白が混じっているだけで違う行判定されたくない……からかな?
なんとなく入れただけだと思われる
よくわからなかったですが、一応修正後のソースコードでも
.trim()
して判別する仕様にしてあります
はーい
2022-12-21完全に忘れてた()
でもinboxみたらちゃんとメモしてあったから
来週から授業ないのでそのへんでやります~
修正した後から思ったのですが、本当にこの仕様(フォーマット挿入関連の仕様)で良かったのかなーってちょっと思い始めている
フォーマットの文章の下に箇条書きで追記しにくくなった
結局のところ、「テンプレート行が分断されるのは許容するが、テンプレート行が1行でも欠損していた場合は新たに挿入し直す」という仕様になりました
前回のdevのソースコードからの差分としては、1行コメントアウトしただけ
単体テストを書いて確認します
なので format.ts
と util.ts
の単体テストだけを書けばいい
$ deno test -r=https://scrapbox.io https://scrapbox.io/api/code/villagepump/pin-diary-6_pull%231/format_test.ts https://scrapbox.io/api/code/villagepump/pin-diary-6_pull%231/util_test.ts
古い変更を言及するのがScrapboxだときつい
例えば今(2023-01-07 14:08:12 )、passさせた単体テストの結果について色々書き込んでいるが、ロジックを修正して単体テストの結果が変わると、コメントの意味がわからなくなる
format_test.tsimport { patchTemplate } from "./format.ts";
import { assertEquals } from "./deps_test.ts";
Deno.test("patchTemplate()", async (t) => {
await t.step("その1", () => {
const headers = [
"header start",
"header content",
"",
"header end",
];
const lines = [
"何か",
"aaa",
"header content",
" コメントが書いてあるかも",
"header end modified",
"",
"本文とか",
"おしまい",
"footer end",
" ↑footerの残骸",
];
const footers = [
"footer start",
"footer content",
"footer end",
];
assertEquals<string[]>(patchTemplate(lines, headers, footers), [
"header start",
"header content",
"",
"header end",
"",
"何か",
"aaa",
"header content",
" コメントが書いてあるかも",
"header end modified",
うーん、ここのheaderが新規追加されちゃうかあ
(まだちゃんとコード読んでいないので、どういう条件でいい感じにformatが復元されるか理解していない)
format_test.ts "",
"本文とか",
"おしまい",
"footer end",
" ↑footerの残骸",
"",
"footer start",
"footer content",
"footer end",
ここも、合体されてほしい
util_test.tsimport { patchLines } from "./util.ts";
import { assertEquals } from "./deps_test.ts";
Deno.test("patchLines()", async (t) => {
await t.step("その1", () => {
const template = [
"template start",
"template template",
"template end",
];
const lines = [
"何か",
"aaa",
"template template",
" コメントが書いてあるかも",
"template end modified",
"",
"本文とか",
"おしまい",
];
assertEquals<string[]>(patchLines(lines, template), [
"template start",
"template template",
"template end",
"何か",
"aaa",
"template template",
" コメントが書いてあるかも",
"template end modified",
"",
"本文とか",
"おしまい",
]);
});
});
deps_test.tsexport * from "https://deno.land/std@0.171.0/testing/asserts.ts";
format.tsimport { findSplitIndex, patchLines } from "./util.ts";
// linesにタイトルを入れないように
export const patchTemplate = (
lines: string[],
headers: string[],
footers: string[],
): string[] => {
// headerとfooterに相当する行を補う
let bodies: string[] = lines;
bodies = patchLines(bodies, headers, "head");
bodies = patchLines(bodies, footers, "tail");
// headerとfooterの間に余裕をもたせる
const headerEnd = findSplitIndex(bodies, headers);
const footerEnd = findSplitIndex(bodies, footers);
if (headerEnd === null || footerEnd === null) {
// バグってテンプレの挿入がうまくいかなかったら諦める
console.log(
"format.tsのコードがバグったためtemplateの挿入を諦めました。\n" +
`headerEnd: ${headerEnd}, footerEnd: ${footerEnd}`,
);
return lines;
}
const footerStart = footerEnd + 1 - footers.length;
return [
...bodies.slice(0, headerEnd + 1),
"",
...bodies.slice(headerEnd + 1, footerStart).join("\n").trim().split("\n"),
"",
...bodies.slice(footerStart),
];
};
util.tsexport const patchLines = (
lines: string[],
appends: string[],
position: "head" | "tail" = "head",
): string[] => {
let appendsIndex = 0;
for (const line of lines) {
if (line.trim() == appends[appendsIndex].trim()) {
if (appendsIndex == appends.length - 1) {
// appendsと完全に一致するパターンが発見されたので行を挿入せずに終了する
return lines;
}
++appendsIndex;
} else {
// 何もしない
// appendsIndex = 0;
}
}
// 一致するパターンが見つからなかった場合はappendsを挿入する
switch (position) {
case "head":
return [...appends, ...lines];
case "tail":
return [...lines, ...appends];
}
};
/** queryに合致するlinesの終了行を返す */
export const findSplitIndex = (
lines: string[],
query: string[],
): number | null => {
let queryCount = 0;
for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
if (lines[lineIndex].trim() == query[queryCount].trim()) {
if (queryCount == query.length - 1) return Number(lineIndex);
++queryCount;
}
}
return null;
};