-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9cbf9c9
commit 6cb3238
Showing
11 changed files
with
506 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
type RootContent = { | ||
readonly contents: ReadonlyArray<HashValue<Content>>; | ||
}; | ||
|
||
/** | ||
* Tのハッシュ値ということ | ||
* value は遅延して渡す | ||
* 内部の定義は適当 | ||
*/ | ||
type HashValue<T> = { | ||
// readonly hashValue: string; | ||
readonly value: T; | ||
}; | ||
|
||
/** | ||
* Tの署名ということ | ||
* 内部の定義は適当 | ||
*/ | ||
type Signature<T> = { | ||
readonly hashValue: HashValue<T>; | ||
readonly value: T; | ||
}; | ||
|
||
type Content = { | ||
/** 初期ハッシュ値でもある */ | ||
readonly id: string; | ||
readonly name: string; | ||
readonly allowWriteAccountIds: ReadonlySet<string>; | ||
readonly contents: ReadonlyArray<Content>; | ||
}; | ||
|
||
type Commit = { | ||
readonly rootContentHashValue: HashValue<RootContent>; | ||
readonly prevContentHashValue: HashValue<RootContent>; | ||
}; | ||
|
||
type SignedCommit = { | ||
readonly commitSign: Signature<Commit>; | ||
readonly commitHash: HashValue<Commit>; | ||
}; | ||
|
||
const getHashContents = ( | ||
hashValues: ReadonlySet<string>, | ||
): ReadonlyMap< | ||
string, | ||
{ | ||
readonly type: "ok"; | ||
readonly content: unknown; | ||
} | { | ||
readonly type: "ng"; | ||
readonly reason: "notFound" | "accessDenied"; | ||
} | ||
> => { | ||
return new Map(); | ||
}; | ||
|
||
const getLastRootContentHash = (): string => { | ||
return ""; | ||
}; | ||
|
||
/** | ||
* IDたちから最新のハッシュ値を取得する | ||
* | ||
* 最新とはって感じではる. そのサーバーで最新だと思われる...? | ||
*/ | ||
const getLastHashByIds = (ids: ReadonlySet<string>): ReadonlyMap< | ||
string, | ||
{ | ||
readonly type: "ok"; | ||
readonly value: unknown; | ||
} | { | ||
readonly type: "ng"; | ||
readonly reason: "notFound"; | ||
} | ||
> => { | ||
return new Map(); | ||
}; | ||
|
||
/** | ||
* IDたちからそのrootContentHashのハッシュ値を取得する | ||
*/ | ||
const getLastHashByIdsAndRootContentHash = ( | ||
ids: ReadonlySet<string>, | ||
rootCotentHash: string, | ||
): ReadonlyMap< | ||
string, | ||
{ | ||
readonly type: "ok"; | ||
readonly value: unknown; | ||
} | { | ||
readonly type: "ng"; | ||
readonly reason: "notFound"; | ||
} | ||
> => { | ||
return new Map(); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
## 編集距離問題 | ||
|
||
IDがない系だと差分を計算するのが大変である | ||
ただIDを必須にすると指定するのが大変だし, | ||
珍しく同一の変更をした場合に差分として出力してしまうこともある... | ||
(DOMの場合そのことは不便になりえるが...) | ||
|
||
動的計画法で文字列を最小操作ポイントで差を埋めるアルゴリズムを書けた. | ||
木構造でこのアルゴリズムは使えるのだろうか? | ||
|
||
ものにIDの変更など, 許可されないような操作があったりするな replace というより | ||
update 可能とか, 不可能とか | ||
|
||
## 関係ないけど definy | ||
|
||
案としてこの世のすべてをモノレポで表現したらどうだろうか? | ||
各ノードでインデックスデータを持つ必要があるが... | ||
|
||
- projectA projectAのハッシュ値 | ||
- projectB projectBのハッシュ値 | ||
|
||
から導き出せる すべてのハッシュ値があるが, 使うことはないか? | ||
いわばワールドハッシュみたいな. | ||
projectCを追加するコミットは作成してサーバーAに送信するときに, | ||
サーバーAから「あれが足りないよ」とか要求されるみたいな | ||
|
||
著作権などで受理を拒否された場合はハッシュ値とIDだけ残るのかな |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { VDom } from "./vdom.ts"; | ||
|
||
export const hydrate = (element: Element, vdom: VDom): void => { | ||
requestAnimationFrame(() => { | ||
// console.log("render", element, vdom); | ||
element.querySelector("a")?.insertBefore(a, b); | ||
element.querySelector("a")?.remove(); | ||
element.querySelector("a")?.append(); | ||
// document.body; | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,47 +1,50 @@ | ||
import { App } from "./app.tsx"; | ||
import { h, hydrate, JSX } from "https://esm.sh/[email protected]?pin=v135"; | ||
import { useState } from "https://esm.sh/[email protected]/hooks?pin=v135"; | ||
import { utils } from "jsr:@noble/secp256k1"; | ||
import { encodeBase64Url } from "jsr:@std/encoding/base64url"; | ||
import { SignUpDialog } from "./SignUpDialog.tsx"; | ||
import { hydrate } from "./render.ts"; | ||
import { div } from "./vdom.ts"; | ||
// import { App } from "./app.tsx"; | ||
// import { h, hydrate, JSX } from "https://esm.sh/[email protected]?pin=v135"; | ||
// import { useState } from "https://esm.sh/[email protected]/hooks?pin=v135"; | ||
// import { utils } from "jsr:@noble/secp256k1"; | ||
// import { encodeBase64Url } from "jsr:@std/encoding/base64url"; | ||
// import { SignUpDialog } from "./SignUpDialog.tsx"; | ||
|
||
const root = document.getElementById("root"); | ||
if (root === null) { | ||
throw new Error("root element not found"); | ||
} | ||
// const root = document.getElementById("root"); | ||
// if (root === null) { | ||
// throw new Error("root element not found"); | ||
// } | ||
|
||
const AppWithState = (): JSX.Element => { | ||
const [state, setState] = useState(0); | ||
const [privateKey, setPrivateKey] = useState<Uint8Array | null>(null); | ||
// const AppWithState = (): JSX.Element => { | ||
// const [state, setState] = useState(0); | ||
// const [privateKey, setPrivateKey] = useState<Uint8Array | null>(null); | ||
|
||
return ( | ||
<div> | ||
<App | ||
state={state} | ||
privateKey={privateKey} | ||
setState={setState} | ||
signUp={() => { | ||
setPrivateKey(utils.randomPrivateKey()); | ||
}} | ||
copyPassword={() => { | ||
if (privateKey === null) { | ||
return; | ||
} | ||
navigator.clipboard.writeText(encodeBase64Url(privateKey)); | ||
}} | ||
/> | ||
<SignUpDialog | ||
privateKey={privateKey} | ||
copyPassword={() => { | ||
if (privateKey === null) { | ||
return; | ||
} | ||
navigator.clipboard.writeText(encodeBase64Url(privateKey)); | ||
}} | ||
onClose={() => setPrivateKey(null)} | ||
/> | ||
</div> | ||
); | ||
}; | ||
// return ( | ||
// <div> | ||
// <App | ||
// state={state} | ||
// privateKey={privateKey} | ||
// setState={setState} | ||
// signUp={() => { | ||
// setPrivateKey(utils.randomPrivateKey()); | ||
// }} | ||
// copyPassword={() => { | ||
// if (privateKey === null) { | ||
// return; | ||
// } | ||
// navigator.clipboard.writeText(encodeBase64Url(privateKey)); | ||
// }} | ||
// /> | ||
// <SignUpDialog | ||
// privateKey={privateKey} | ||
// copyPassword={() => { | ||
// if (privateKey === null) { | ||
// return; | ||
// } | ||
// navigator.clipboard.writeText(encodeBase64Url(privateKey)); | ||
// }} | ||
// onClose={() => setPrivateKey(null)} | ||
// /> | ||
// </div> | ||
// ); | ||
// }; | ||
|
||
hydrate(<AppWithState />, root); | ||
// hydrate(<AppWithState />, root); | ||
hydrate(document.documentElement, div({}, "aaa")); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
// vdom の処理 | ||
// レンダリングを要求されたら, | ||
// 前回のvdomと今回のvdomを比較する, 変更点を出力する | ||
// 変更点から実DOMへ反映する | ||
|
||
// この構造だとcomponentのように状態管理できん! | ||
// componentの木構造を比較するようにすれば良い? | ||
|
||
export type VDom = { | ||
readonly elementName: string; | ||
readonly attributeMap: ReadonlyMap<string, string>; | ||
readonly children: ReadonlyArray<VDom> | string; | ||
}; | ||
|
||
export const div = ( | ||
attribute: { readonly id?: string }, | ||
children: ReadonlyArray<VDom> | string, | ||
): VDom => ({ | ||
elementName: "div", | ||
attributeMap: new Map([ | ||
...(attribute.id | ||
? [ | ||
["id", attribute.id], | ||
] as const | ||
: []), | ||
]), | ||
children, | ||
}); | ||
|
||
export const vdomToString = (vdom: VDom): string => | ||
`<${vdom.elementName}${ | ||
vdom.attributeMap.size === 0 | ||
? "" | ||
: ` ${[...vdom.attributeMap].map(([k, v]) => `${k}="${v}"`).join(" ")}` | ||
}>${ | ||
typeof vdom.children === "string" | ||
? vdom.children.replaceAll("<", ">") | ||
: vdom.children.map(vdomToString).join("") | ||
}</${vdom.elementName}>`; | ||
|
||
export const vdomToHtml = (vdom: VDom): string => { | ||
return "<!doctype html>" + vdomToString(vdom); | ||
}; | ||
|
||
type Diff = { | ||
readonly type: "remove"; | ||
readonly path: ReadonlyArray<number>; | ||
} | { | ||
readonly type: "insertBefore"; | ||
readonly path: ReadonlyArray<number>; | ||
readonly newNode: VDom; | ||
readonly index: number | undefined; | ||
} | { | ||
readonly type: "setAttribute"; | ||
readonly path: ReadonlyArray<number>; | ||
} | { | ||
readonly type: "setTextContent"; | ||
readonly path: ReadonlyArray<number>; | ||
readonly value: string; | ||
} | { | ||
readonly type: "impossible"; | ||
}; | ||
|
||
export const diff = (oldVDom: VDom, newVDom: VDom): ReadonlyArray<Diff> => { | ||
if (typeof newVDom.children === "string") { | ||
if (typeof oldVDom.children === "string") { | ||
if (oldVDom.children === newVDom.children) { | ||
return []; | ||
} else { | ||
return [ | ||
{ | ||
type: "setTextContent", | ||
path: [], | ||
value: newVDom.children, | ||
}, | ||
]; | ||
} | ||
} else { | ||
return [ | ||
{ | ||
type: "setTextContent", | ||
path: [], | ||
value: newVDom.children, | ||
}, | ||
]; | ||
} | ||
} else { | ||
if (typeof oldVDom.children === "string") { | ||
return newVDom.children.map((child) => ({ | ||
type: "insertBefore", | ||
index: undefined, | ||
newNode: child, | ||
path: [], | ||
})); | ||
} else { | ||
// 編集距離とかあるよなぁ... | ||
|
||
// A B C | ||
// から | ||
// B D C | ||
// に | ||
} | ||
} | ||
}; |
Oops, something went wrong.