サンプル
@tiptap/pm 3.11.0: closeHistory
検証済みサンプル — npm @tiptap/pm 3.11.0: closeHistory. node 22 · linux debian/x64 · docker で contract を実行し、成功しました: closeHistory is a function exported by…
sha256:e891c5be5f9cc4058d624f5750ddeb4ec8d5eedb9357d9eef75cbd49c72d84c4
このネットワークが提供するのは一つだけです。ビルドされるサンプル。サンドボックスで実行し、署名済みの受領証を保管します。等級はつけず、何も保証しません — 同じコードがあなたの環境でビルドされるかは測定していません。
合格した契約受領証を提出した異なる署名鍵の数です。1 なら作者だけ、2 以上なら他の誰かもビルドしています。鍵は自己生成で背後に登録された身元がないため、数えているのは人ではなく鍵です。
MIT-0
実行証拠
宣言された環境と署名済みの実行を分けてあります。このサンプルが何をどこで実行したかをそのまま確認できます。
- 証拠の基準
- 署名済みコントラクト合格
- 検証レシート
- 1
- ビルドした署名鍵
- 1
宣言された環境
node 22.23 linux 24 · ubuntu · glibc 2.39 x64 node 22.23 javascript npm 10
検証実行環境
| 環境 | コントラクト | ステージ | 実行日 |
|---|---|---|---|
| node 22 · linux debian/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1node:22@sha256:8a34c4ab3ea2… |
2026-09-15 |
ケース
HOW- ゴール
- verify @tiptap/pm.closeHistory in pkg:npm/%40tiptap/pm@3.11.0
- パッケージ
- シンボル
-
- @tiptap/pm.closeHistory
- 環境
- node 22.23.2
- 作成日
- 2026-09-15T03:38:53Z
コントラクト
- closeHistory is a function exported by @tiptap/pm/history
- closeHistory accepts a Transaction and returns the same transaction instance
- consecutive edits within newGroupDelay merge into a single history event by default
- applying closeHistory on a transaction closes the active history group so subsequent edits create a new event
- closeHistory attached directly to an edit transaction starts a new history group
- undo reverts only the edits made after closeHistory leaving earlier edits in the previous history event
- subsequent undo operations revert earlier history events after the closed event is undone
- redo re-applies history events in sequence respecting boundaries set by closeHistory
- applying closeHistory without document modifications leaves document content and selection unchanged
- calling closeHistory on initial editor state with empty history does not cause errors or increase undoDepth
ファイル
- PROMPT.md
- csx.json
- index.mjs
- package-lock.json
- package.json
- spec.json
- test/contract.mjs
ソース
Clean-room public code sample — generation instructions
Write a brand-new, minimal, self-contained code sample in this clean-room directory.
Do not copy, paraphrase, or reference any existing project source. Work only from this spec.
A csx.json manifest scaffold already exists. Do not recreate it from memory. Preserve its case.goal, packages and symbols; fill its empty case.contract with exact assertions and correct its environment, commands and verifierAdapter for the files you generate.
Goal: verify @tiptap/pm.closeHistory in pkg:npm/%40tiptap/pm@3.11.0
Kind: HOW
Use EXACTLY these public packages and versions:
- pkg:npm/%40tiptap/pm@3.11.0
Demonstrate these symbols/APIs:
- @tiptap/pm.closeHistory
Rules:
- One focused purpose; the smallest project that proves the goal.
- Include a contract test (test/contract.*) that runs OFFLINE and exits 0 exactly when the goal behavior works.
- Pin every dependency with a lockfile so resolution is reproducible.
- No secrets, credentials, or tokens. No real URLs (only example.com or localhost). No absolute paths.
- No personal names, emails, company names, or project identifiers of any kind.
- No binaries and no generated output (node_modules, dist, target, venv, .git, .env).
- Keep it under 200 files and 256KB packed.
{"case":{"caseId":"case:sha256:c2369d13f9342fed6c7bd580a52c16291f66bf9357ec91562423f0242240381c","contract":["closeHistory is a function exported by @tiptap/pm/history","closeHistory accepts a Transaction and returns the same transaction instance","consecutive edits within newGroupDelay merge into a single history event by default","applying closeHistory on a transaction closes the active history group so subsequent edits create a new event","closeHistory attached directly to an edit transaction starts a new history group","undo reverts only the edits made after closeHistory leaving earlier edits in the previous history event","subsequent undo operations revert earlier history events after the closed event is undone","redo re-applies history events in sequence respecting boundaries set by closeHistory","applying closeHistory without document modifications leaves document content and selection unchanged","calling closeHistory on initial editor state with empty history does not cause errors or increase undoDepth"],"goal":"verify @tiptap/pm.closeHistory in pkg:npm/%40tiptap/pm@3.11.0","kind":"HOW","packages":["pkg:npm/%40tiptap/pm@3.11.0"],"schemaVersion":1,"symbols":["@tiptap/pm.closeHistory"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","distro":"ubuntu","ecosystem":"npm","executionContext":"node","language":"javascript","libc":"glibc","libcVersion":"2.39","os":"linux","osVersionBucket":"24","packageManager":"npm","packageManagerVersion":"10.9.8","runtime":"node","runtimeVersion":"22.23.2","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/%40tiptap/pm@3.11.0"],"schemaVersion":1,"subject":"pkg:npm/%40tiptap/pm@3.11.0","symbols":["@tiptap/pm.closeHistory"],"verifierAdapter":"node-typescript@1"}
import {
closeHistory,
history,
undo,
redo,
undoDepth,
redoDepth
} from '@tiptap/pm/history';
import { EditorState } from '@tiptap/pm/state';
import { schema } from '@tiptap/pm/schema-basic';
export {
closeHistory,
history,
undo,
redo,
undoDepth,
redoDepth,
EditorState,
schema
};
export default closeHistory;
{
"name": "sample-tiptap-pm-closehistory",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "sample-tiptap-pm-closehistory",
"version": "1.0.0",
"dependencies": {
"@tiptap/pm": "3.11.0"
}
},
"node_modules/@remirror/core-constants": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-3.0.0.tgz",
"integrity": "sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==",
"license": "MIT"
},
"node_modules/@tiptap/pm": {
"version": "3.11.0",
"resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.11.0.tgz",
"integrity": "sha512-plCQDLCZIOc92cizB8NNhBRN0szvYR3cx9i5IXo6v9Xsgcun8KHNcJkesc2AyeqdIs0BtOJZaqQ9adHThz8UDw==",
"license": "MIT",
"dependencies": {
"prosemirror-changeset": "^2.3.0",
"prosemirror-collab": "^1.3.1",
"prosemirror-commands": "^1.6.2",
"prosemirror-dropcursor": "^1.8.1",
"prosemirror-gapcursor": "^1.3.2",
"prosemirror-history": "^1.4.1",
"prosemirror-inputrules": "^1.4.0",
"prosemirror-keymap": "^1.2.2",
"prosemirror-markdown": "^1.13.1",
"prosemirror-menu": "^1.2.4",
"prosemirror-model": "^1.24.1",
"prosemirror-schema-basic": "^1.2.3",
"prosemirror-schema-list": "^1.5.0",
"prosemirror-state": "^1.4.3",
"prosemirror-tables": "^1.6.4",
"prosemirror-trailing-node": "^3.0.0",
"prosemirror-transform": "^1.10.2",
"prosemirror-view": "^1.38.1"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
}
},
"node_modules/@types/linkify-it": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz",
"integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==",
"license": "MIT"
},
"node_modules/@types/markdown-it": {
"version": "14.2.0",
"resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.2.0.tgz",
"integrity": "sha512-NoQ2yGlLWj4wpxMs+TYmRKk3thDrQ97agr7sFqfLsAlvoS8SNQuTrlObhFqG9iugdTtgOE9jpJ6FNM4ZGsa5xQ==",
"license": "MIT",
"dependencies": {
"@types/linkify-it": "^5",
"@types/mdurl": "^2"
}
},
"node_modules/@types/mdurl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz",
"integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==",
"license": "MIT"
},
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"license": "Python-2.0"
},
"node_modules/crelt": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.7.tgz",
"integrity": "sha512-aK6BbWfhf4U/wCcLHKPJl/xa6VkVstRaPywWtMKGwuOLc/wZTyQYuoxgvZnNsBvv7Kg3YTBQYYBCggcviQczuA==",
"license": "MIT"
},
"node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/linkify-it": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.2.tgz",
"integrity": "sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/puzrin"
},
{
"type": "github",
"url": "https://github.com/sponsors/markdown-it"
}
],
"license": "MIT",
"dependencies": {
"uc.micro": "^2.0.0"
}
},
"node_modules/markdown-it": {
"version": "14.3.2",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.3.2.tgz",
"integrity": "sha512-sHHjZ5fJKlgrG4qns2YwVcdNep35h5fERrfkD2YNsb9UFk0UIHarbiTaHKVMlPuWAoiilyK8Fv/jAm11slsY7Q==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/puzrin"
},
{
"type": "github",
"url": "https://github.com/sponsors/markdown-it"
}
],
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1",
"entities": "^4.5.0",
"linkify-it": "^5.0.2",
"mdurl": "^2.0.0",
"punycode.js": "^2.3.1",
"uc.micro": "^2.1.0"
},
"bin": {
"markdown-it": "bin/markdown-it.mjs"
}
},
"node_modules/mdurl": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.1.0.tgz",
"integrity": "sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg==",
"license": "MIT"
},
"node_modules/orderedmap": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz",
"integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==",
"license": "MIT"
},
"node_modules/prosemirror-changeset": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.4.2.tgz",
"integrity": "sha512-ViYrjMSg3YFiXwIhKaluu+/mi3Yrxt6AR8ri14ulTaGcZtXO1CThl7A2gv79qx5fQnOw8woKwyBU2u+9PVCm3w==",
"license": "MIT",
"dependencies": {
"prosemirror-transform": "^1.0.0"
}
},
"node_modules/prosemirror-collab": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/prosemirror-collab/-/prosemirror-collab-1.3.1.tgz",
"integrity": "sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==",
"license": "MIT",
"dependencies": {
"prosemirror-state": "^1.0.0"
}
},
"node_modules/prosemirror-commands": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.7.2.tgz",
"integrity": "sha512-q6Q6szxqdu9Xd6EcdKsqXghu5nQdZTpB4Q9yd04WRc7/jt763e/rT60Owh0L1GYY+T46o5rD+9lEN36dZS43tw==",
"license": "MIT",
"dependencies": {
"prosemirror-model": "^1.0.0",
"prosemirror-state": "^1.0.0",
"prosemirror-transform": "^1.10.2"
}
},
"node_modules/prosemirror-dropcursor": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.3.tgz",
"integrity": "sha512-FoYbsJR8gK+DGlqhNoE29Loa38eIZPzQRIb1VMaDNBoo4OLP6vVof/jR8qFY/6XvUd6Dhug8MDCHl2a/h8RTfQ==",
"license": "MIT",
"dependencies": {
"prosemirror-state": "^1.0.0",
"prosemirror-transform": "^1.1.0",
"prosemirror-view": "^1.1.0"
}
},
"node_modules/prosemirror-gapcursor": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.4.1.tgz",
"integrity": "sha512-pMdYaEnjNMSwl11yjEGtgTmLkR08m/Vl+Jj443167p9eB3HVQKhYCc4gmHVDsLPODfZfjr/MmirsdyZziXbQKw==",
"license": "MIT",
"dependencies": {
"prosemirror-keymap": "^1.0.0",
"prosemirror-model": "^1.0.0",
"prosemirror-state": "^1.0.0",
"prosemirror-view": "^1.0.0"
}
},
"node_modules/prosemirror-history": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.5.0.tgz",
"integrity": "sha512-zlzTiH01eKA55UAf1MEjtssJeHnGxO0j4K4Dpx+gnmX9n+SHNlDqI2oO1Kv1iPN5B1dm5fsljCfqKF9nFL6HRg==",
"license": "MIT",
"dependencies": {
"prosemirror-state": "^1.2.2",
"prosemirror-transform": "^1.0.0",
"prosemirror-view": "^1.31.0",
"rope-sequence": "^1.3.0"
}
},
"node_modules/prosemirror-inputrules": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.5.1.tgz",
"integrity": "sha512-7wj4uMjKaXWAQ1CDgxNzNtR9AlsuwzHfdFH1ygEHA2KHF2DOEaXl1CJfNPAKCg9qNEh4rum975QLaCiQPyY6Fw==",
"license": "MIT",
"dependencies": {
"prosemirror-state": "^1.0.0",
"prosemirror-transform": "^1.0.0"
}
},
"node_modules/prosemirror-keymap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.3.tgz",
"integrity": "sha512-4HucRlpiLd1IPQQXNqeo81BGtkY8Ai5smHhKW9jjPKRc2wQIxksg7Hl1tTI2IfT2B/LgX6bfYvXxEpJl7aKYKw==",
"license": "MIT",
"dependencies": {
"prosemirror-state": "^1.0.0",
"w3c-keyname": "^2.2.0"
}
},
"node_modules/prosemirror-markdown": {
"version": "1.13.7",
"resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.13.7.tgz",
"integrity": "sha512-NV57Oxe3fXR+bNGXS5XW4sKt/XGIyY3n0eHVUoJORcismeF4FFMpLBnl0YESy2BvJQHloexX+9P+zT3VqFj/CQ==",
"license": "MIT",
"dependencies": {
"@types/markdown-it": "^14.0.0",
"markdown-it": "^14.0.0",
"prosemirror-model": "^1.25.0"
}
},
"node_modules/prosemirror-menu": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.3.2.tgz",
"integrity": "sha512-6VgUJTYod0nMBlCaYJGhXGLu7Gt4AvcwcOq0YfJCY/6Uh+3S7UsWhpy6rJFCBFOmonq1hD8KyWOtZhkppd4YPg==",
"license": "MIT",
"dependencies": {
"crelt": "^1.0.0",
"prosemirror-commands": "^1.0.0",
"prosemirror-history": "^1.0.0",
"prosemirror-state": "^1.0.0"
}
},
"node_modules/prosemirror-model": {
"version": "1.25.11",
"resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.11.tgz",
"integrity": "sha512-QWg9RhnpLlogAmp3p96uEFrE5txQpFynd4vhBAELkwgOCWQs/X0yCzB3/hrHqiPwf91RG5KyWq6553zs9JqIOQ==",
"license": "MIT",
"dependencies": {
"orderedmap": "^2.0.0"
}
},
"node_modules/prosemirror-schema-basic": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.4.tgz",
"integrity": "sha512-ELxP4TlX3yr2v5rM7Sb70SqStq5NvI15c0j9j/gjsrO5vaw+fnnpovCLEGIcpeGfifkuqJwl4fon6b+KdrODYQ==",
"license": "MIT",
"dependencies": {
"prosemirror-model": "^1.25.0"
}
},
"node_modules/prosemirror-schema-list": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.5.1.tgz",
"integrity": "sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==",
"license": "MIT",
"dependencies": {
"prosemirror-model": "^1.0.0",
"prosemirror-state": "^1.0.0",
"prosemirror-transform": "^1.7.3"
}
},
"node_modules/prosemirror-state": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.4.tgz",
"integrity": "sha512-6jiYHH2CIGbCfnxdHbXZ12gySFY/fz/ulZE333G6bPqIZ4F+TXo9ifiR86nAHpWnfoNjOb3o5ESi7J8Uz1jXHw==",
"license": "MIT",
"dependencies": {
"prosemirror-model": "^1.0.0",
"prosemirror-transform": "^1.0.0",
"prosemirror-view": "^1.27.0"
}
},
"node_modules/prosemirror-tables": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.8.5.tgz",
"integrity": "sha512-V/0cDCsHKHe/tfWkeCmthNUcEp1IVO3p6vwN8XtwE9PZQLAZJigbw3QoraAdfJPir4NKJtNvOB8oYGKRl+t0Dw==",
"license": "MIT",
"dependencies": {
"prosemirror-keymap": "^1.2.3",
"prosemirror-model": "^1.25.4",
"prosemirror-state": "^1.4.4",
"prosemirror-transform": "^1.10.5",
"prosemirror-view": "^1.41.4"
}
},
"node_modules/prosemirror-trailing-node": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/prosemirror-trailing-node/-/prosemirror-trailing-node-3.0.0.tgz",
"integrity": "sha512-xiun5/3q0w5eRnGYfNlW1uU9W6x5MoFKWwq/0TIRgt09lv7Hcser2QYV8t4muXbEr+Fwo0geYn79Xs4GKywrRQ==",
"license": "MIT",
"dependencies": {
"@remirror/core-constants": "3.0.0",
"escape-string-regexp": "^4.0.0"
},
"peerDependencies": {
"prosemirror-model": "^1.22.1",
"prosemirror-state": "^1.4.2",
"prosemirror-view": "^1.33.8"
}
},
"node_modules/prosemirror-transform": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.12.1.tgz",
"integrity": "sha512-t4F5615FycnCqsX7ShTUs8+jfnwcf46kuFRvSl/3qFx2QTZ4DjgowesLHQXcFP7G//TjesqZG3WtgL7vdyVJyA==",
"license": "MIT",
"dependencies": {
"prosemirror-model": "^1.21.0"
}
},
"node_modules/prosemirror-view": {
"version": "1.42.3",
"resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.42.3.tgz",
"integrity": "sha512-oTN7EtH+CpwxU9NrwEYWd0UZ4JUx7l048l5A2Xppm4p/60isZYLnth9QVQmC3VRIvdrIWCxwZSd+Uz791G31/w==",
"license": "MIT",
"dependencies": {
"prosemirror-model": "^1.25.8",
"prosemirror-state": "^1.0.0",
"prosemirror-transform": "^1.1.0"
}
},
"node_modules/punycode.js": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
"integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/rope-sequence": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz",
"integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==",
"license": "MIT"
},
"node_modules/uc.micro": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
"integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
"license": "MIT"
},
"node_modules/w3c-keyname": {
"version": "2.2.8",
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
"license": "MIT"
}
}
}
{
"name": "sample-tiptap-pm-closehistory",
"version": "1.0.0",
"type": "module",
"private": true,
"dependencies": {
"@tiptap/pm": "3.11.0"
}
}
{
"schemaVersion": 1,
"goal": "verify @tiptap/pm.closeHistory in pkg:npm/%40tiptap/pm@3.11.0",
"kind": "HOW",
"packages": [
"pkg:npm/%40tiptap/pm@3.11.0"
],
"symbols": [
"@tiptap/pm.closeHistory"
]
}
import assert from 'node:assert/strict';
import {
closeHistory,
history,
undo,
redo,
undoDepth,
redoDepth,
EditorState,
schema
} from '../index.mjs';
// 1. closeHistory is a function exported by @tiptap/pm/history
{
assert.equal(typeof closeHistory, 'function', 'closeHistory must be a function');
}
// 2. closeHistory accepts a Transaction and returns the same transaction instance
{
const state = EditorState.create({ schema, plugins: [history()] });
const tr = state.tr;
const returnedTr = closeHistory(tr);
assert.equal(returnedTr, tr, 'closeHistory must return the same transaction instance');
}
// 3. consecutive edits within newGroupDelay merge into a single history event by default
{
let state = EditorState.create({ schema, plugins: [history()] });
state = state.apply(state.tr.insertText('First'));
state = state.apply(state.tr.insertText(' Second'));
assert.equal(state.doc.textContent, 'First Second');
assert.equal(undoDepth(state), 1, 'consecutive edits should merge into 1 event');
assert.equal(redoDepth(state), 0);
}
// 4. applying closeHistory on a transaction closes the active history group so subsequent edits create a new event
{
let state = EditorState.create({ schema, plugins: [history()] });
state = state.apply(state.tr.insertText('First'));
assert.equal(undoDepth(state), 1);
state = state.apply(closeHistory(state.tr));
state = state.apply(state.tr.insertText(' Second'));
assert.equal(state.doc.textContent, 'First Second');
assert.equal(undoDepth(state), 2, 'subsequent edit after closeHistory must create a new event');
}
// 5. closeHistory attached directly to an edit transaction starts a new history group
{
let state = EditorState.create({ schema, plugins: [history()] });
state = state.apply(state.tr.insertText('First'));
assert.equal(undoDepth(state), 1);
state = state.apply(closeHistory(state.tr.insertText(' Second')));
assert.equal(state.doc.textContent, 'First Second');
assert.equal(undoDepth(state), 2, 'edit with closeHistory must start a new event');
}
// 6. undo reverts only the edits made after closeHistory leaving earlier edits in the previous history event
{
let state = EditorState.create({ schema, plugins: [history()] });
state = state.apply(state.tr.insertText('First'));
state = state.apply(closeHistory(state.tr));
state = state.apply(state.tr.insertText(' Second'));
let undoSuccess = undo(state, (tr) => { state = state.apply(tr); });
assert.equal(undoSuccess, true);
assert.equal(state.doc.textContent, 'First', 'first undo should only revert Second');
assert.equal(undoDepth(state), 1);
assert.equal(redoDepth(state), 1);
}
// 7. subsequent undo operations revert earlier history events after the closed event is undone
{
let state = EditorState.create({ schema, plugins: [history()] });
state = state.apply(state.tr.insertText('First'));
state = state.apply(closeHistory(state.tr));
state = state.apply(state.tr.insertText(' Second'));
undo(state, (tr) => { state = state.apply(tr); });
assert.equal(state.doc.textContent, 'First');
let secondUndo = undo(state, (tr) => { state = state.apply(tr); });
assert.equal(secondUndo, true);
assert.equal(state.doc.textContent, '', 'second undo should revert First');
assert.equal(undoDepth(state), 0);
assert.equal(redoDepth(state), 2);
}
// 8. redo re-applies history events in sequence respecting boundaries set by closeHistory
{
let state = EditorState.create({ schema, plugins: [history()] });
state = state.apply(state.tr.insertText('First'));
state = state.apply(closeHistory(state.tr));
state = state.apply(state.tr.insertText(' Second'));
undo(state, (tr) => { state = state.apply(tr); });
undo(state, (tr) => { state = state.apply(tr); });
assert.equal(state.doc.textContent, '');
let firstRedo = redo(state, (tr) => { state = state.apply(tr); });
assert.equal(firstRedo, true);
assert.equal(state.doc.textContent, 'First', 'first redo should restore First');
assert.equal(undoDepth(state), 1);
assert.equal(redoDepth(state), 1);
let secondRedo = redo(state, (tr) => { state = state.apply(tr); });
assert.equal(secondRedo, true);
assert.equal(state.doc.textContent, 'First Second', 'second redo should restore Second');
assert.equal(undoDepth(state), 2);
assert.equal(redoDepth(state), 0);
}
// 9. applying closeHistory without document modifications leaves document content and selection unchanged
{
let state = EditorState.create({ schema, plugins: [history()] });
state = state.apply(state.tr.insertText('Unchanged text'));
const prevDoc = state.doc;
const prevSel = state.selection;
state = state.apply(closeHistory(state.tr));
assert.equal(state.doc, prevDoc, 'document must not change');
assert.equal(state.selection.from, prevSel.from);
assert.equal(state.selection.to, prevSel.to);
}
// 10. calling closeHistory on initial editor state with empty history does not cause errors or increase undoDepth
{
let state = EditorState.create({ schema, plugins: [history()] });
assert.equal(undoDepth(state), 0);
state = state.apply(closeHistory(state.tr));
assert.equal(undoDepth(state), 0, 'undoDepth must remain 0');
assert.equal(redoDepth(state), 0, 'redoDepth must remain 0');
assert.equal(undo(state), false, 'undo must return false on empty history');
}
console.log('All @tiptap/pm.closeHistory contract tests passed successfully.');
オリジンシーダー
匿名