diff --git a/browser/dom/mod.ts b/browser/dom/mod.ts index b046f36..9455b1a 100644 --- a/browser/dom/mod.ts +++ b/browser/dom/mod.ts @@ -11,3 +11,4 @@ export * from "./cache.ts"; export * from "./cursor.ts"; export * from "./selection.ts"; export * from "./stores.ts"; +export * from "./pushPageTransition.ts"; diff --git a/browser/dom/open.ts b/browser/dom/open.ts index 3657bb4..22dc0d3 100644 --- a/browser/dom/open.ts +++ b/browser/dom/open.ts @@ -3,6 +3,10 @@ /// import { encodeTitleURI } from "../../title.ts"; +import { + PageTransitionContext, + pushPageTransition, +} from "./pushPageTransition.ts"; import type { Scrapbox } from "../../deps/scrapbox.ts"; declare const scrapbox: Scrapbox; @@ -24,6 +28,9 @@ export interface OpenOptions { * @default 同じprojectの場合は再読み込みせず、違うprojectの場合は再読込する */ reload?: boolean; + + /** リンク先へスクロールする機能を使うために必要な情報 */ + context?: Omit; } /** ページを開く @@ -41,6 +48,12 @@ export const open = ( if (options?.body) url.search = `?body=${encodeURIComponent(options.body)}`; if (options?.id) url.hash = `#${options.id}`; + if (options?.context) { + pushPageTransition( + { ...options?.context, to: { project, title } } as PageTransitionContext, + ); + } + if ( options?.newTab !== false && (options?.newTab === true || project !== scrapbox.Project.name) diff --git a/browser/dom/pushPageTransition.ts b/browser/dom/pushPageTransition.ts new file mode 100644 index 0000000..0a167f4 --- /dev/null +++ b/browser/dom/pushPageTransition.ts @@ -0,0 +1,66 @@ +import { toTitleLc } from "../../title.ts"; + +/** ページリンク */ +export interface Link { + /** リンク先のproject name */ + project: string; + + /** リンク先のpage title */ + title: string; +} + +/** ページから別のページに遷移するときの状態を表す */ +export interface PageTransitionContextLink { + type: "page"; + + /** 遷移元ページのリンク */ + from: Link; + + /** 遷移先ページのリンク */ + to: Link; +} + +/** 全文検索結果から別のページに遷移するときの状態を表す */ +export interface PageTransitionContextQuery { + type: "search"; + + /** 全文検索での検索語句 */ + query: string; + + /** 遷移先ページのリンク */ + to: Link; +} + +export type PageTransitionContext = + | PageTransitionContextLink + | PageTransitionContextQuery; + +/** ページ遷移状態を登録し、次回のページ遷移時にリンク先へスクロールする + * + * @param context 遷移状態 + */ +export const pushPageTransition = (context: PageTransitionContext): void => { + const pageTransitionContext: Record = JSON.parse( + localStorage.getItem("pageTransitionContext") ?? "", + ); + const value = context.type === "page" + ? context.from.project === context.to.project + ? context.from.title === context.to.title + ? { + titleHint: context.to.title, + } + : { + linkFrom: context.from.title, + } + : { + linkFrom: `/${context.from.project}/${context.from.title}`, + } + : { + searchQuery: context.query, + }; + pageTransitionContext[`page_${toTitleLc(context.to.title)}`] = value; + localStorage.setItem( + "pageTransitionContext", + JSON.stringify(pageTransitionContext), + ); +}; diff --git a/title.test.ts b/title.test.ts index 42d2134..be71ce0 100644 --- a/title.test.ts +++ b/title.test.ts @@ -8,7 +8,10 @@ import { assertStrictEquals } from "./deps/testing.ts"; Deno.test("toTitleLc()", async (t) => { await t.step("` ` -> `_`", () => { - assertStrictEquals(toTitleLc("空白入り タイトル"), "空白入り_タイトル"); + assertStrictEquals( + toTitleLc("空白入り タイトル"), + "空白入り_タイトル", + ); assertStrictEquals( toTitleLc(" 前後にも 空白入り _タイトル "), "_前後にも_空白入り__タイトル_",