CodeMirror 6 language support package for 1C:Enterprise (BSL) and OneScript — Russian and English keyword syntax, preprocessor directives, compilation annotations, multi-line string literals, and embedded query language (SDBL) inside string literals.
https://1c-syntax.github.io/codemirror-lang-bsl/ — two side-by-side
CodeMirror 6 editors: one with a sample BSL module (procedure with annotation,
control flow, async function, region), another with a function whose query
string body is highlighted by the embedded SDBL grammar. Add ?theme=light to
the URL for the light theme.
API reference (generated from JSDoc with TypeDoc): https://1c-syntax.github.io/codemirror-lang-bsl/api/.
The grammar is implemented in Lezer, references
the 1c-syntax/bsl-parser ANTLR4
grammars for structure and the
1c-syntax/vsc-language-1c-bsl
TextMate grammar for token style mapping.
npm install @1c-syntax/codemirror-lang-bslimport {EditorView, basicSetup} from "codemirror"
import {bsl} from "@1c-syntax/codemirror-lang-bsl"
new EditorView({
doc: 'Процедура Привет() Экспорт\n Сообщить("Привет, мир!");\nКонецПроцедуры',
extensions: [basicSetup, bsl()],
parent: document.body
})- Module-level: variable declarations (
Перем/Var), procedure/function declarations withЭкспорт, default parameters andЗнач/Val, async modifierАСИНХ - Control flow:
Если/ИначеЕсли/Иначе/КонецЕсли,Пока/КонецЦикла,Для … По … Цикл/КонецЦикла,Для Каждого … Из/КонецЦикла,Попытка/Исключение/КонецПопытки - Statements:
Возврат/Продолжить/Прервать/Перейти, labels~Метка:,Ждатьas both standalone statement and expression,ВызватьИсключение,Выполнить,ДобавитьОбработчик/УдалитьОбработчик - Expressions: number literals, string literals (single-line and multi-line
with
|continuation), date literals'YYYYMMDDHHMMSS', booleansИстина/Ложь,Неопределено,Null,Новый, ternary?(…) - Operators: arithmetic, comparison, logical (
И/Или/Не) - Annotations:
&НаКлиенте,&НаСервере,&НаКлиентеНаСервереБезКонтекста, … including annotation parameters - Preprocessor:
#Если/#ИначеЕсли/#Иначе/#КонецЕсли,#Область/#КонецОбласти,#Использовать,#native - Comments:
//(single-line),///(BSLDescription doc-comments) - SDBL (BSL query language) embedded inside query string literals —
a separate Lezer grammar covering 100+ keywords (statement / operator /
function / type / metadata-object / virtual-table categories) is mounted
as an overlay onto any string literal that starts with
ВЫБРАТЬ/SELECT/УНИЧТОЖИТЬ/DROP. Russian and English keyword variants are both recognised and styled identically.
The grammar and style mapping are derived from the following 1c-syntax projects. When updating this package, diff against the recorded commit to catch grammar changes upstream.
| Project | Used for | Pinned commit | Tag |
|---|---|---|---|
1c-syntax/bsl-parser |
Lexer/parser structure (BSL + SDBL ANTLR4 grammars) | a30f8169885836226208041fbc41001bd64d710e |
v0.34.1 |
1c-syntax/vsc-language-1c-bsl |
TextMate scope reference (1c.tmLanguage.json, 1c-query.tmLanguage.json) |
30e6c7994a2ee745c92fa0238fa2e81c78d4781d |
v1.33.1 |
1c-syntax/bsl-language-server |
Semantic-token → LSP token type mapping (SemanticTokensProvider, *SemanticTokensSupplier) — pinned against the active develop branch, not the latest release |
be49fcbf45d082a1db15504b51a551f6a55183c0 (develop) |
latest release at the time: v0.29.0 |
To re-sync after an upstream change: bump the relevant pinned commit in the
table above, replay the upstream diff against src/bsl.grammar and
src/index.ts (styleTags), and add regression tests in test/cases.txt.
A handful of intentional simplifications, mostly to keep the LR grammar free of ambiguity:
- Context-sensitive preprocessor identifiers.
#Если/#Иначе/#КонецЕсли/#Тогда/#И/#Или/#Неreuse the corresponding BSL keyword terms — styleTags discriminates them via parent selectors. The remaining preprocessor-only words (Область,КонецОбласти,Использовать,native,Удаление/КонецУдаления,Вставка/КонецВставки) are specialized globally; if you use one as an ordinary identifier outside#context, it will be tagged as a preprocessor token. BSL convention does not collide with these names in practice. - Comma-skipping in call arguments (
Метод(a,,b)orМетод(,a)) is not supported — modelling,as a stand-alone item conflicts with innerf(g(...))parsing in LR(1) without a custom external tokenizer. All arguments must be non-empty expressions. Affects roughly 1–2% of real-world BSL. - Multiline strings cannot contain embedded preprocessor directives.
ANTLR's
multilineString : STRINGSTART (STRINGPART | BAR | preprocessor)* STRINGTAILaccepts#Еслиinside a|-continued string; we match the entire literal as one token. Very rare in practice.
Verified against ~100 real-world configuration files
(1c-syntax/bsl-language-server and 1c-syntax/vsc-language-1c-bsl
fixtures): 85% clean parses, 0 hard failures, the remaining ~15% are
either intentional ParseError test cases, source-level typos, or hit one
of the three limitations above.
Out of scope (defer to other tools):
- IntelliSense / completion / hover — that belongs in
bsl-language-server. - Refactorings, diagnostics — same.
npm install
npm run build # runs lezer-generator + rollup + tsc
npm test # mocha against test/cases.txt fixturesThe repo ships a public-npm .npmrc so contributors on networks that default
to a private mirror (e.g. corporate Artifactory) still resolve packages from
https://registry.npmjs.org/. Publishing requires a separate npm login
against the public registry.
The hosted version at https://1c-syntax.github.io/codemirror-lang-bsl/ is
deployed automatically by .github/workflows/pages.yml on every push to
main. To build the demo locally:
npm install
npm run lint # ESLint (flat config) on src/, examples/, test/
npm run build # main library → dist/
npm test # mocha against test/cases.txt and overlay tests
npm run build:demo # static demo → docs/{index.html,bundle.js}
npm run build:docs # TypeDoc API reference → docs/api/
npm run build:site # demo + docs (CI uses this for gh-pages)
# serve docs/ via any HTTP server, e.g.
python3 -m http.server -d docs 8080examples/demo.ts is the source; examples/index.html is the HTML shell that
the rollup config copies into docs/index.html alongside the bundled
bundle.js.
Releases are cut by publishing a GitHub Release with a tag of the form
v<version> (matching package.json#version). The
.github/workflows/publish.yml workflow builds, tests, and runs
npm publish --provenance --access public against npmjs.org. Authentication
is done via npm Trusted Publishing
— no long-lived NPM_TOKEN secret is needed; npm exchanges the workflow's
OIDC token for a short-lived credential at publish time.
- https://www.npmjs.com/package/@1c-syntax/codemirror-lang-bsl/access → Trusted Publishers → Add
- Provider: GitHub Actions
- Repository owner:
1c-syntax, Repository:codemirror-lang-bsl - Workflow file name:
publish.yml - Environment:
npm
That's it — no secrets, no tokens. The workflow's id-token: write
permission plus --provenance are enough; npm verifies the OIDC token
against the configured trusted publisher and accepts the upload.
- Bump
package.json#version, commit, push. - https://github.com/1c-syntax/codemirror-lang-bsl/releases/new →
tag
v<version>(matchingpackage.json#version) → Publish release. - The
Publish to npmworkflow picks up therelease.publishedevent, verifies tag-vs-version, builds, tests, and runsnpm publish.
workflow_dispatch on Publish to npm accepts a dry_run input. Run it
to validate auth, build, and tarball contents without actually publishing.
MIT — see LICENSE.