@cratis/screenplay-language

中文文档
6.18.0发布于 2026/11/11MITTypeScriptES Module零依赖构建来源已验证近 30 天下载 3.5万

Monaco language service for the Cratis Screenplay DSL — syntax highlighting, IntelliSense, hover and diagnostics for .play files

原始使用文档
文档目录6 节
  1. Usage
  2. What is covered
  3. Quick fixes
  4. Extending with new sub-languages
  5. Building
  6. Runtime size budget

@cratis/screenplay-language

Monaco language service for the Cratis Screenplay DSL (.play files) — syntax highlighting, IntelliSense completions, hover documentation, and diagnostics.

Usage

import * as monaco from 'monaco-editor';
import { register } from '@cratis/screenplay-language';

register(monaco);

register is the single entry point. It registers the screenplay language (.play extension), the Monarch tokenizer, the completion and hover providers, the diagnostics watcher, and the screenplay-dark / screenplay-light themes on the Monaco instance you pass in. monaco-editor is a peer dependency — the package never bundles Monaco.

import { languageId, screenplayDarkThemeName, screenplayLightThemeName } from '@cratis/screenplay-language';

monaco.editor.create(element, {
    language: languageId,
    theme: screenplayDarkThemeName,
});

What is covered

  • Highlighting — all construct and clause keywords, slice types, concept attributes (@pii, @sensitive), context variables ($context.*, $env.*, $eventContext.*, $.\*), strings, numbers, and comments.
  • Embedded code blocks — csharp, java, typescript, react, and html blocks between triple backticks are highlighted with Monaco's own language grammars.
  • Sub-languages — the PDL (projection) and CDL (capture) bodies are tokenized by their own registered rules using Monarch's state stack.
  • Completions — context-aware by enclosing construct (top level, module, feature, slice, command, produces, handler, screen, constraint, …), plus in-scope symbol names: policies after authorize, events after on and produces, concepts and primitives in type positions, and resolvable module/feature targets after depends on, nearest scope first, excluding targets already declared.
  • Hover — keyword documentation, concept definitions (primitive + attributes), policy require expressions, and event property lists.
  • Diagnostics — unknown slice types, unknown primitive types, references to undeclared policies and events, tab indentation, and unclosed code fences. Every one of them carries the compiler's own PLAY code (diagnosticCodes), so a squiggle and a CLI diagnostic for the same condition are the same code.

Quick fixes

The registered code-action provider offers verified edits against the current buffer:

  • PLAY0479: replace one legacy ? suffix with optional, or migrate the document.
  • PLAY0471: remove a redundant event id line. Trailing comments prevent removal.

Redundant id removal works in placed and multi-document applications. Actions respect the requested diagnostic and kind, cache analysis per model version, and pin edits to that version. Range requests return every eligible intersecting occurrence, without duplicate actions. Independent recipes are verified together once per version to check the intended syntax changes and diagnostic removal without reparsing per marker; no .NET process is required. See editor quick fixes for the redundant id removal behavior.

Extending with new sub-languages

import { registerSubLanguage } from '@cratis/screenplay-language';

registerSubLanguage('workflow', {
    tokens: [[/\b(?:start|step|end)\b/, 'keyword']],
    completions: [{ label: 'step', insertText: 'step ${1:Name}', documentation: 'A workflow step.' }],
    hovers: { step: 'Workflow — a step executed in sequence.' },
});

Registration works before or after register(monaco); the tokenizer recomposes on the fly. See the sub-language documentation for the full design.

Building

yarn build

The published runtime is an ES module graph under dist/bundles/, not a shared prebuilt chunk. The root, capture, and projection entry paths are unchanged. Private compiler modules ship as relative files under dist/bundles/compiler/; consumers do not need to install @cratis/screenplay-compiler. Consumers can now tree-shake and split these modules using their own bundler configuration. Callable names, minification, and source maps are preserved.

check-package.mjs checks the packed tarball, resolves every public entry with only declared peers installed, and prints the ten largest modules, total runtime bytes, and the minified size of a consumer importing register, languageId, and screenplayDarkThemeName. Runtime sizes exclude declarations and source maps.

Runtime size budget

  • Every published JavaScript file must be ≤ 500,000 bytes. This is the consumer chunk budget and is never raised; split the module graph rather than growing a prebuilt chunk.
  • The total runtime must be ≤ 1,000,000 bytes. This ceiling approves language growth within that limit while guarding against vendored dependencies. Growth beyond it requires explicit approval after reviewing the module breakdown, not an automatic ceiling increase each release. Monaco remains external.
  • A consumer's final chunks still depend on its bundler's splitting configuration; a module graph does not guarantee that a single bundled consumer stays under 500,000 bytes.

The module-graph build initially emits 199 JavaScript files totaling 752,551 bytes. Its ten largest modules are:

Module (relative to dist/bundles/)Bytes
completion-items.js41,933
compiler/Syntax/SyntaxCollections.js29,257
keyword-docs.js23,414
compiler/Syntax/ScreenplaySyntaxWalker.js20,450
compiler/Parsing/SpecificationParser.js19,931
compiler/Diagnostics/DiagnosticCodes.js14,235
sub-languages/projection/CompletionProvider.js13,391
event-source-authoring.js12,877
validation.js12,806
compiler/Parsing/ScreenParser.js12,351

The packed consumer smoke import bundles to 601,682 bytes as a single minified module with Monaco external. The breakdown contains no printer or MCP-only provenance modules. Syntax serialization initialization is still pulled in by compiler barrel exports; removing it requires a separate, behavior-checked compiler import cleanup rather than dropping parser validators from the editor.

yarn test:pack also runs size-check specifications with a planted oversized module. The guard must reject it and name its published path.

版本与发布记录

@cratis/screenplay-language 共发布 413 个版本,首次发布于 2026/07/29;过去 12 个月发布了 413 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
6.18.0latest2026/11/11今天
6.17.02026/11/11今天
6.16.02026/11/10今天
6.15.02026/11/10今天
6.14.02026/11/10今天
6.13.02026/11/10今天

关于 @cratis/screenplay-language 的常见问题

@cratis/screenplay-language 是什么?

Monaco language service for the Cratis Screenplay DSL — syntax highlighting, IntelliSense, hover and diagnostics for .play files

如何安装 @cratis/screenplay-language?

在项目目录运行 npm install @cratis/screenplay-language,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:monaco-editor(>=0.44.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@cratis/screenplay-language 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@cratis/screenplay-language 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@cratis/screenplay-language 可以商用吗?

@cratis/screenplay-language 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@cratis/screenplay-language 的下载量有多少?

根据 npm 官方下载统计,@cratis/screenplay-language 在 2026/10/11 – 2026/11/09 这 30 天内被下载 34,583 次,日均约 1,153 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@cratis/screenplay-language 还在维护吗?

最新版本 6.18.0 发布于 2026/11/11(今天);至今共发布 413 个版本,其中过去 12 个月发布了 413 个;首次发布于 2026/07/29。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。