Skip to content

feat(patch): update()の第2引数から、Pageの全データを取り出せるようにした #165

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
- uses: actions/checkout@v2
- uses: denoland/setup-deno@v1
with:
deno-version: "1.36.1"
deno-version: "v1.x"
- name: Check fmt
run: deno fmt --check
- name: Run lint
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/udd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
- uses: actions/checkout@v2
- uses: denoland/setup-deno@v1
with:
deno-version: "1.36.1"
deno-version: "v1.x"
- name: Update dependencies
run: >
deno run --allow-net --allow-read --allow-write=deps/
Expand Down
4 changes: 2 additions & 2 deletions browser/dom/click.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ export const holdDown = async (
target: element,
clientX: options.X,
clientY: options.Y,
pageX: options.X + window.scrollX,
pageY: options.Y + window.scrollY,
pageX: options.X + globalThis.scrollX,
pageY: options.Y + globalThis.scrollY,
});
const mouseOptions = {
button: options.button ?? 0,
Expand Down
2 changes: 1 addition & 1 deletion browser/dom/extractCodeFiles.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { extractCodeFiles } from "./extractCodeFiles.ts";
import { Line } from "../../deps/scrapbox.ts";
import { assertSnapshot } from "../../deps/testing.ts";
import sample from "./sample-lines1.json" assert { type: "json" };
import sample from "./sample-lines1.json" with { type: "json" };

Deno.test("extractCodeFiles", async (t) => {
await assertSnapshot(
Expand Down
2 changes: 1 addition & 1 deletion browser/dom/isHeightViewable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

export const isHeightViewable = (element: HTMLElement): boolean => {
const { top, bottom } = element.getBoundingClientRect();
return top >= 0 && bottom <= window.innerHeight;
return top >= 0 && bottom <= globalThis.innerHeight;
};
2 changes: 1 addition & 1 deletion browser/dom/motion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ const getVisibleLineCount = (): number => {
if (clientHeight === undefined) {
throw Error("Could not find .line:last-of-type");
}
return Math.round(window.innerHeight / clientHeight);
return Math.round(globalThis.innerHeight / clientHeight);
};

/** 半ページ上にスクロールする
Expand Down
4 changes: 2 additions & 2 deletions browser/dom/open.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,14 @@ export const open = (
options?.newTab !== false &&
(options?.newTab === true || project !== scrapbox.Project.name)
) {
window.open(url);
globalThis.open(url);
return;
}
if (
options?.reload !== false &&
(options?.reload === true || project !== scrapbox.Project.name)
) {
window.open(url, "_self");
globalThis.open(url, "_self");
return;
}

Expand Down
8 changes: 4 additions & 4 deletions browser/websocket/_codeBlock.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Change, Socket, wrap } from "../../deps/socket.ts";
import { Page } from "../../deps/scrapbox-rest.ts";
import { TinyCodeBlock } from "../../rest/getCodeBlocks.ts";
import { HeadData } from "./pull.ts";
import { getProjectId, getUserId } from "./id.ts";
import { pushWithRetry } from "./_fetch.ts";

Expand All @@ -14,7 +14,7 @@ export interface CodeTitle {
/** コミットを送信する一連の処理 */
export const applyCommit = async (
commits: Change[],
head: HeadData,
page: Page,
projectName: string,
pageTitle: string,
socket: Socket,
Expand All @@ -26,9 +26,9 @@ export const applyCommit = async (
]);
const { request } = wrap(socket);
return await pushWithRetry(request, commits, {
parentId: head.commitId,
parentId: page.commitId,
projectId: projectId,
pageId: head.pageId,
pageId: page.id,
userId: userId_,
project: projectName,
title: pageTitle,
Expand Down
2 changes: 1 addition & 1 deletion browser/websocket/deletePage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const deletePage = async (
options?: DeletePageOptions,
): Promise<void> => {
const [
{ pageId, commitId: parentId, persistent },
{ id: pageId, commitId: parentId, persistent },
projectId,
userId,
] = await Promise.all([
Expand Down
21 changes: 10 additions & 11 deletions browser/websocket/makeChanges.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import { diffToChanges } from "./diffToChanges.ts";
import type { Line } from "../../deps/scrapbox.ts";
import { Block, Node, parse } from "../../deps/scrapbox.ts";
import { Block, Line, Node, parse } from "../../deps/scrapbox.ts";
import { Page } from "../../deps/scrapbox-rest.ts";
import type { Change } from "../../deps/socket.ts";
import type { HeadData } from "./pull.ts";
import { toTitleLc } from "../../title.ts";
import { parseYoutube } from "../../parser/youtube.ts";

export interface Init {
userId: string;
head: HeadData;
page: Page;
}
export function* makeChanges(
left: Pick<Line, "text" | "id">[],
right: string[],
{ userId, head }: Init,
{ userId, page }: Init,
): Generator<Change, void, unknown> {
// 改行文字が入るのを防ぐ
const right_ = right.flatMap((text) => text.split("\n"));
Expand All @@ -24,7 +23,7 @@ export function* makeChanges(

// titleの差分を入れる
// 空ページの場合もタイトル変更commitを入れる
if (left[0].text !== right_[0] || !head.persistent) {
if (left[0].text !== right_[0] || !page.persistent) {
yield { title: right_[0] };
}

Expand All @@ -38,18 +37,18 @@ export function* makeChanges(
// リンクと画像の差分を入れる
const [links, projectLinks, image] = findLinksAndImage(right_.join("\n"));
if (
head.links.length !== links.length ||
!head.links.every((link) => links.includes(link))
page.links.length !== links.length ||
!page.links.every((link) => links.includes(link))
) {
yield { links };
}
if (
head.projectLinks.length !== projectLinks.length ||
!head.projectLinks.every((link) => projectLinks.includes(link))
page.projectLinks.length !== projectLinks.length ||
!page.projectLinks.every((link) => projectLinks.includes(link))
) {
yield { projectLinks };
}
if (head.image !== image) {
if (page.image !== image) {
yield { image };
}
}
Expand Down
36 changes: 22 additions & 14 deletions browser/websocket/patch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,22 @@ import { Socket, socketIO, wrap } from "../../deps/socket.ts";
import { connect, disconnect } from "./socket.ts";
import { getProjectId, getUserId } from "./id.ts";
import { makeChanges } from "./makeChanges.ts";
import { HeadData, pull } from "./pull.ts";
import type { Line } from "../../deps/scrapbox-rest.ts";
import { pull } from "./pull.ts";
import { Line, Page } from "../../deps/scrapbox-rest.ts";
import { pushCommit, pushWithRetry } from "./_fetch.ts";

export interface PatchOptions {
socket?: Socket;
}

export interface PatchMetadata extends Page {
/** 書き換えを再試行した回数
*
* 初回は`0`で、再試行するたびに増える
*/
retry: number;
}

/** ページ全体を書き換える
*
* serverには書き換え前後の差分だけを送信する
Expand All @@ -24,12 +32,12 @@ export const patch = async (
title: string,
update: (
lines: Line[],
metadata: HeadData,
metadata: PatchMetadata,
) => string[] | undefined | Promise<string[] | undefined>,
options?: PatchOptions,
): Promise<void> => {
const [
head_,
page_,
projectId,
userId,
] = await Promise.all([
Expand All @@ -38,7 +46,7 @@ export const patch = async (
getUserId(),
]);

let head = head_;
let page = page_;

const injectedSocket = options?.socket;
const socket = injectedSocket ?? await socketIO();
Expand All @@ -47,43 +55,43 @@ export const patch = async (
const { request } = wrap(socket);

// 3回retryする
for (let i = 0; i < 3; i++) {
for (let retry = 0; retry < 3; retry++) {
try {
const pending = update(head.lines, head);
const pending = update(page.lines, { ...page, retry });
const newLines = pending instanceof Promise ? await pending : pending;

if (!newLines) return;

if (newLines.length === 0) {
await pushWithRetry(request, [{ deleted: true }], {
projectId,
pageId: head.pageId,
parentId: head.commitId,
pageId: page.id,
parentId: page.commitId,
userId,
project,
title,
});
}

const changes = [
...makeChanges(head.lines, newLines, { userId, head }),
...makeChanges(page.lines, newLines, { userId, page }),
];
await pushCommit(request, changes, {
parentId: head.commitId,
parentId: page.commitId,
projectId,
pageId: head.pageId,
pageId: page.id,
userId,
});
break;
} catch (_e: unknown) {
if (i === 2) {
if (retry === 2) {
throw Error("Faild to retry pushing.");
}
console.log(
"Faild to push a commit. Retry after pulling new commits",
);
try {
head = await pull(project, title);
page = await pull(project, title);
} catch (e: unknown) {
throw e;
}
Expand Down
18 changes: 9 additions & 9 deletions browser/websocket/pin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const pin = async (
options?: PinOptions,
): Promise<void> => {
const [
head,
page,
projectId,
userId,
] = await Promise.all([
Expand All @@ -37,12 +37,12 @@ export const pin = async (
]);

// 既にピン留めされている場合は何もしない
if (head.pin > 0 || (!head.persistent && !(options?.create ?? false))) return;
if (page.pin > 0 || (!page.persistent && !(options?.create ?? false))) return;

const init = {
parentId: head.commitId,
parentId: page.commitId,
projectId,
pageId: head.pageId,
pageId: page.id,
userId,
project,
title,
Expand All @@ -53,7 +53,7 @@ export const pin = async (
const { request } = wrap(socket);

// タイトルのみのページを作る
if (!head.persistent) {
if (!page.persistent) {
const commitId = await pushWithRetry(request, [{ title }], init);
init.parentId = commitId;
}
Expand All @@ -79,7 +79,7 @@ export const unpin = async (
options: UnPinOptions,
): Promise<void> => {
const [
head,
page,
projectId,
userId,
] = await Promise.all([
Expand All @@ -89,12 +89,12 @@ export const unpin = async (
]);

// 既にピンが外れているか、そもそも存在しないページの場合は何もしない
if (head.pin == 0 || !head.persistent) return;
if (page.pin == 0 || !page.persistent) return;

const init = {
parentId: head.commitId,
parentId: page.commitId,
projectId,
pageId: head.pageId,
pageId: page.id,
userId,
project,
title,
Expand Down
27 changes: 3 additions & 24 deletions browser/websocket/pull.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,16 @@
import type { Line } from "../../deps/scrapbox-rest.ts";
import { Page } from "../../deps/scrapbox-rest.ts";
import { getPage } from "../../rest/pages.ts";

export interface HeadData {
commitId: string;
pageId: string;
persistent: boolean;
image: string | null;
pin: number;
links: string[];
projectLinks: string[];
lines: Line[];
}
export const pull = async (
project: string,
title: string,
): Promise<HeadData> => {
): Promise<Page> => {
const result = await getPage(project, title);

// TODO: 編集不可なページはStream購読だけ提供する
if (!result.ok) {
throw new Error(`You have no privilege of editing "/${project}/${title}".`);
}
const { commitId, persistent, image, links, projectLinks, lines, id, pin } =
result.value;

return {
commitId,
pageId: id,
persistent,
image,
links,
projectLinks,
pin,
lines,
};
return result.value;
};
4 changes: 2 additions & 2 deletions rest/__snapshots__/pages.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Request {
headers: Headers {},
method: "GET",
redirect: "follow",
url: "https://scrapbox.io/api/pages/takker/%E3%83%86%E3%82%B9%E3%83%88%E3%83%9A%E3%83%BC%E3%82%B8?followRe"... 9 more characters
url: "https://scrapbox.io/api/pages/takker/%E3%83%86%E3%82%B9%E3%83%88%E3%83%9A%E3%83%BC%E3%82%B8?followRename=true",
}
`;

Expand All @@ -16,6 +16,6 @@ Request {
headers: Headers {},
method: "GET",
redirect: "follow",
url: "https://scrapbox.io/api/pages/takker?sort=updated"
url: "https://scrapbox.io/api/pages/takker?sort=updated",
}
`;
Loading