Skip to content

1c-syntax/codemirror-lang-bsl

Repository files navigation

@1c-syntax/codemirror-lang-bsl

npm CI License: MIT

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.

👉 Live demo

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.

Install

npm install @1c-syntax/codemirror-lang-bsl

Usage

import {EditorView, basicSetup} from "codemirror"
import {bsl} from "@1c-syntax/codemirror-lang-bsl"

new EditorView({
  doc: 'Процедура Привет() Экспорт\n    Сообщить("Привет, мир!");\nКонецПроцедуры',
  extensions: [basicSetup, bsl()],
  parent: document.body
})

What's covered

  • 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.

Upstream references

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.

Limitations

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 inner f(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)* STRINGTAIL accepts #Если 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.

Build & test

npm install
npm run build   # runs lezer-generator + rollup + tsc
npm test        # mocha against test/cases.txt fixtures

The 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.

Demo

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 8080

examples/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.

Publishing a release

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.

Setup (one-time)

  1. https://www.npmjs.com/package/@1c-syntax/codemirror-lang-bsl/accessTrusted PublishersAdd
  2. Provider: GitHub Actions
  3. Repository owner: 1c-syntax, Repository: codemirror-lang-bsl
  4. Workflow file name: publish.yml
  5. 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.

Cutting a release

  1. Bump package.json#version, commit, push.
  2. https://github.com/1c-syntax/codemirror-lang-bsl/releases/new → tag v<version> (matching package.json#version) → Publish release.
  3. The Publish to npm workflow picks up the release.published event, verifies tag-vs-version, builds, tests, and runs npm publish.

Dry-run before cutting

workflow_dispatch on Publish to npm accepts a dry_run input. Run it to validate auth, build, and tarball contents without actually publishing.

License

MIT — see LICENSE.

About

1C:Enterprise / OneScript (BSL) language support for CodeMirror 6 with embedded SDBL query language highlighting

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors