Пример
@tiptap/extension-highlight 3.11.0
Проверенный пример — npm @tiptap/extension-highlight 3.11.0. Контракт выполнен на node 22 · linux debian/x64 · docker и пройден.
sha256:4b03b9948662d7b6c20ac924fe35f7be6af9af88cec9f9e45463f473a83fd61d
Эта сеть предлагает одно: образец, который собирается. Она запустила его в песочнице и сохранила подписанную квитанцию. Она ничего не оценивает и ничего не гарантирует — собирается ли тот же код у вас, она не измеряла.
Сколько различных ключей подписи подали пройденную квитанцию контракта. Один — только автор; больше одного — значит, кто-то ещё тоже собрал. Ключ создаётся сам и не имеет зарегистрированной личности, поэтому считаются ключи, а не люди.
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-11 |
Кейс
HOW- Цель
- verify pkg:npm/%40tiptap/extension-highlight@3.11.0
- Окружение
- node 22.23.2
- Создан
- 2026-09-11T14:17:58Z
Контракт
- Highlight extension exports Mark named highlight with default options
- Highlight extension configure updates multicolor and HTMLAttributes options
- Highlight parses mark tag and renders mark element with configured attributes
- Highlight multicolor attribute renders background-color and data-color attributes
- Highlight defines inputRegex and pasteRegex for markdown syntax matching
Файлы
- PROMPT.md
- csx.json
- package-lock.json
- package.json
- spec.json
- src/index.js
- 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 pkg:npm/%40tiptap/extension-highlight@3.11.0
Kind: HOW
Use EXACTLY these public packages and versions:
- pkg:npm/%40tiptap/extension-highlight@3.11.0
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:92f5becfc865cf5ad66a8d230e8a52c424bfaa8641725410305815f4357ef1b8","contract":["Highlight extension exports Mark named highlight with default options","Highlight extension configure updates multicolor and HTMLAttributes options","Highlight parses mark tag and renders mark element with configured attributes","Highlight multicolor attribute renders background-color and data-color attributes","Highlight defines inputRegex and pasteRegex for markdown syntax matching"],"goal":"verify pkg:npm/%40tiptap/extension-highlight@3.11.0","kind":"HOW","packages":["pkg:npm/%40tiptap/extension-highlight@3.11.0"],"schemaVersion":1},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","distro":"ubuntu","ecosystem":"npm","language":"javascript","libc":"glibc","libcVersion":"2.39","moduleSystem":"cjs","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/extension-highlight@3.11.0"],"schemaVersion":1,"subject":"pkg:npm/%40tiptap/extension-highlight@3.11.0","verifierAdapter":"node-typescript@1"}
{
"name": "sample-tiptap-extension-highlight",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "sample-tiptap-extension-highlight",
"version": "1.0.0",
"license": "MIT-0",
"dependencies": {
"@tiptap/extension-highlight": "3.11.0"
}
},
"node_modules/@tiptap/core": {
"version": "3.31.3",
"resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.31.3.tgz",
"integrity": "sha512-Cz50pvciQrxdSxgTkHOVz0uD0Yl/8Xt0QatGD6ILm47jW8EzyHR9RkUGs/D5IqzXKuVPntfw1ttaT926vXfiRg==",
"license": "MIT",
"peer": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/pm": "3.31.3"
}
},
"node_modules/@tiptap/extension-highlight": {
"version": "3.11.0",
"resolved": "https://registry.npmjs.org/@tiptap/extension-highlight/-/extension-highlight-3.11.0.tgz",
"integrity": "sha512-1Yzz77Nr4JB22WwAHKgfBsO+4fTaDdCsYVx9HDFkfGk6hliATwtNXvoi/7srfNjSpZzLUeqmPLjOhx3WS/hwtw==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
},
"peerDependencies": {
"@tiptap/core": "^3.11.0"
}
},
"node_modules/@tiptap/pm": {
"version": "3.31.3",
"resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.31.3.tgz",
"integrity": "sha512-sZime0SWsz/k62W2WvHx5Ig7G2h7kVhrrmnqy+wEgIHfDwEfOlelRjaWCiBCFlF7dxGUntJusCh9FxlLhni0Ag==",
"license": "MIT",
"peer": true,
"dependencies": {
"prosemirror-changeset": "^2.4.1",
"prosemirror-commands": "^1.7.1",
"prosemirror-dropcursor": "^1.8.2",
"prosemirror-gapcursor": "^1.4.1",
"prosemirror-history": "^1.5.0",
"prosemirror-inputrules": "^1.5.1",
"prosemirror-keymap": "^1.2.3",
"prosemirror-model": "^1.25.11",
"prosemirror-schema-list": "^1.5.1",
"prosemirror-state": "^1.4.4",
"prosemirror-tables": "^1.8.5",
"prosemirror-transform": "^1.12.0",
"prosemirror-view": "^1.42.3"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/ueberdosis"
}
},
"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",
"peer": true
},
"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",
"peer": true,
"dependencies": {
"prosemirror-transform": "^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",
"peer": true,
"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",
"peer": true,
"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",
"peer": true,
"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",
"peer": true,
"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",
"peer": true,
"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",
"peer": true,
"dependencies": {
"prosemirror-state": "^1.0.0",
"w3c-keyname": "^2.2.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",
"peer": true,
"dependencies": {
"orderedmap": "^2.0.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",
"peer": true,
"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",
"peer": true,
"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",
"peer": true,
"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-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",
"peer": true,
"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",
"peer": true,
"dependencies": {
"prosemirror-model": "^1.25.8",
"prosemirror-state": "^1.0.0",
"prosemirror-transform": "^1.1.0"
}
},
"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",
"peer": true
},
"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",
"peer": true
}
}
}
{
"name": "sample-tiptap-extension-highlight",
"version": "1.0.0",
"private": true,
"description": "verify pkg:npm/@tiptap/extension-highlight@3.11.0",
"main": "src/index.js",
"license": "MIT-0",
"dependencies": {
"@tiptap/extension-highlight": "3.11.0"
}
}
{
"schemaVersion": 1,
"goal": "verify pkg:npm/%40tiptap/extension-highlight@3.11.0",
"kind": "HOW",
"packages": [
"pkg:npm/%40tiptap/extension-highlight@3.11.0"
]
}
const { Highlight, inputRegex, pasteRegex } = require('@tiptap/extension-highlight');
function createHighlightExtension(options = {}) {
return Highlight.configure(options);
}
function getHighlightName() {
return Highlight.name;
}
function getHighlightType() {
return Highlight.type;
}
module.exports = {
Highlight,
inputRegex,
pasteRegex,
createHighlightExtension,
getHighlightName,
getHighlightType
};
import assert from 'node:assert/strict';
import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
const { Highlight: directHighlight, inputRegex: directInputRegex, pasteRegex: directPasteRegex } = require('@tiptap/extension-highlight');
const {
Highlight,
inputRegex,
pasteRegex,
createHighlightExtension,
getHighlightName,
getHighlightType
} = require('../src/index.js');
// 1. Highlight extension exports Mark named highlight with default options
{
assert.equal(Highlight, directHighlight, 'Highlight should match direct import');
assert.equal(getHighlightName(), 'highlight', 'Extension name should be highlight');
assert.equal(getHighlightType(), 'mark', 'Extension type should be mark');
assert.equal(Highlight.name, 'highlight', 'Highlight.name should be highlight');
assert.equal(Highlight.type, 'mark', 'Highlight.type should be mark');
assert.deepEqual(
Highlight.options,
{ multicolor: false, HTMLAttributes: {} },
'Default options should have multicolor false and empty HTMLAttributes'
);
}
// 2. Highlight extension configure updates multicolor and HTMLAttributes options
{
const configured = createHighlightExtension({
multicolor: true,
HTMLAttributes: { class: 'custom-highlight' }
});
assert.equal(configured.name, 'highlight', 'Configured extension name should remain highlight');
assert.equal(configured.type, 'mark', 'Configured extension type should remain mark');
assert.equal(configured.options.multicolor, true, 'multicolor option should be true');
assert.deepEqual(
configured.options.HTMLAttributes,
{ class: 'custom-highlight' },
'HTMLAttributes option should match configured object'
);
}
// 3. Highlight parses mark tag and renders mark element with configured attributes
{
const parseRules = Highlight.config.parseHTML();
assert.ok(Array.isArray(parseRules), 'parseHTML should return an array');
assert.deepEqual(parseRules, [{ tag: 'mark' }], 'parseHTML should match mark tag');
const renderedWithClass = Highlight.config.renderHTML.call(
{ options: { multicolor: false, HTMLAttributes: { class: 'hl' } } },
{ HTMLAttributes: {} }
);
assert.deepEqual(
renderedWithClass,
['mark', { class: 'hl' }, 0],
'renderHTML should merge configured HTMLAttributes with mark tag'
);
const renderedMerged = Highlight.config.renderHTML.call(
{ options: { multicolor: false, HTMLAttributes: { class: 'hl' } } },
{ HTMLAttributes: { 'data-id': 'highlight-1' } }
);
assert.deepEqual(
renderedMerged,
['mark', { class: 'hl', 'data-id': 'highlight-1' }, 0],
'renderHTML should merge dynamic and configured attributes'
);
}
// 4. Highlight multicolor attribute renders background-color and data-color attributes
{
const monoAttributes = Highlight.config.addAttributes.call({
options: { multicolor: false }
});
assert.deepEqual(monoAttributes, {}, 'addAttributes should be empty when multicolor is disabled');
const multiAttributes = Highlight.config.addAttributes.call({
options: { multicolor: true }
});
assert.ok(multiAttributes.color, 'color attribute should exist when multicolor is enabled');
assert.equal(multiAttributes.color.default, null, 'default color should be null');
const renderedColor = multiAttributes.color.renderHTML({ color: '#ffcc00' });
assert.deepEqual(
renderedColor,
{
'data-color': '#ffcc00',
style: 'background-color: #ffcc00; color: inherit'
},
'renderHTML should set data-color and style when color is provided'
);
const renderedNoColor = multiAttributes.color.renderHTML({});
assert.deepEqual(renderedNoColor, {}, 'renderHTML should return empty object when no color is set');
const parsedFromDataColor = multiAttributes.color.parseHTML({
getAttribute: (name) => (name === 'data-color' ? '#ff0000' : null),
style: {}
});
assert.equal(parsedFromDataColor, '#ff0000', 'parseHTML should prioritize data-color');
const parsedFromStyle = multiAttributes.color.parseHTML({
getAttribute: () => null,
style: { backgroundColor: '#00ff00' }
});
assert.equal(parsedFromStyle, '#00ff00', 'parseHTML should fall back to style.backgroundColor');
}
// 5. Highlight defines inputRegex and pasteRegex for markdown syntax matching
{
assert.equal(inputRegex, directInputRegex, 'inputRegex should match direct export');
assert.equal(pasteRegex, directPasteRegex, 'pasteRegex should match direct export');
assert.ok(inputRegex instanceof RegExp, 'inputRegex should be a RegExp instance');
assert.ok(pasteRegex instanceof RegExp, 'pasteRegex should be a RegExp instance');
assert.equal(inputRegex.test('==highlighted=='), true, 'inputRegex should match ==text==');
assert.equal(inputRegex.test('plain text'), false, 'inputRegex should not match plain text');
const pasteMatches = 'Sample text ==highlighted== more text'.match(pasteRegex);
assert.ok(Array.isArray(pasteMatches), 'pasteRegex should find matches');
assert.equal(pasteMatches[0].trim(), '==highlighted==', 'pasteRegex should match ==highlighted==');
}
console.log('All @tiptap/extension-highlight contract assertions passed successfully.');
Исходный сидер
аноним