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(" 前後にも 空白入り _タイトル "),
"_前後にも_空白入り__タイトル_",