@feugene/granularity-code

  • С компонентами
  • релизов: 9
  • v1.1.0

Релизы @feugene/granularity-code из его CHANGELOG: последние 8 целиком, более ранние — списком версий.

тег ядра v1.1.1

На этой странице

Записи релизов — авторский текст библиотеки, и он английский. Портал его не переводит: журнал изменений — история чужого репозитория, а переписанная история перестаёт быть историей.

v1.1.02026-10-16

Changed

  • Peer @feugene/granum — >=2.0.0 <3.0.0. Пакет собран granum 2.0: dist не импортирует granum — контракт встроен в dist/granum/contract.js, и SSR-сервер с внешними пакетами, задеплоенный с --omit=dev, больше не падает с ERR_MODULE_NOT_FOUND. Приложению — @feugene/granum и @feugene/granum-engine-wind ^2.0.0.
  • Компонент из корня пакета — ComponentRootImportError у приложения на granum 2.0. Компоненты берут из <пакет>/components/<Имя>.
  • Авто-импорт — один GranularityResolver() из @feugene/unplugin-granularity 1.1: он находит пакет в package.json приложения сам, порядок резолверов больше не важен. Собственный ./resolver остаётся для уже написанных конфигов.
  • Необязательный peer @feugene/fint-i18n — >=0.9.0 <1.0.0. Пакет тестируется на 0.9 вместе с ядром; на 0.7 и 0.8 он не проверялся.

v1.0.42026-10-13

Fixed

  • Подписи пропуска GrDiff без i18n согласуют число. Словари пакета держат формы one/other, а встроенный запасной текст был одной строкой во множественном числе: приложение без адаптера i18n показывало «Show 1 more lines». Теперь запасной английский текст выбирает форму сам — у expand, expandTop, expandBottom и hidden.

v1.0.32026-10-06

Fixed

  • Замечания validate у GrCodeEditor видны в тексте. Проп обещал «подчёркивание в месте и метку в жёлобе», а декорации строились только для ролей подсветки: замечание было лишь пунктом списка под полем. Теперь у каждого замечания волнистое подчёркивание на [from, to) в тоне важности (точечное расширяется до символа), метка в отдельной колонке жёлоба на его строке с текстом в title, а пункт списка начинается со строки и столбца («Line 3, column 11 — Error: …»). Колонка держит ширину, пока задан validate; ответ асинхронного validate доезжает до подчёркивания тоже. Цвета — хуки --gr-code-editor-issue-error/-warning/-info поверх ролей текста тонов, без темы CodeMirror.
  • Сбой сериализации GrCodeBlock портит только своё значение. Штатный JSON.stringify зовёт toJSON раньше replacer, и один враждебный toJSON обрывал весь вызов: объект с ошибкой, релизом, BigInt-идентификатором, циклическим запросом и полем customer, чей toJSON бросает, печатался одной строкой [Unserializable]. Теперь значение обходится своим кодом, toJSON и чтение каждого поля идут в своём try, и маркер "[Unserializable]" встаёт только на место упавшего значения — соседи, [Circular] и BigInt с n остаются. Так же для геттеров, которые бросают, и для GrDiff (serializeStable).

Documentation

  • Появились описания у пропов, событий и методов GrCodeBlock, GrCodeEditor и GrDiff, которые в API и на портале были пустыми.

v1.0.22026-10-06

Changed

  • Safelist компонентов пуст. Все записи лежали в коде целыми литералами — в шаблонах и .ts-хелперах, включая общую поверхность internal/codeSurface.ts. granum извлекает такие классы сам, обходя от входа компонента все его чанки, общие включительно, и вычищал записи из манифеста как уже извлечённые. Списки пережили UnoCSS-пресет, который общий чанк не сканировал. Набор классов не изменился — проверено сверкой манифестов по селекции каждого компонента; расходятся только случайные токены, которые экстрактор выхватывает из минифицированного кода.
  • Удалён internal/classTokens.ts: он служил только спискам.
  • Подключён гейт defineSafelistGate из test-kit: запись safelist, которая лежит целым литералом в коде компонента, он называет лишней. Нужен safelist только классу, собранному в рантайме из частей.

v1.0.12026-09-29

Починка доставки CSS. Публичная поверхность не менялась, обновление безопасное.

Fixed

  • CSS компонента больше не доставляется дважды. Сборка пакета звала libInjectCss(), и тот вписывал в JS-чанк каждого компонента import '../styles.css'. До granum это был единственный канал доставки стилей. С granum тот же файл приезжает приложению через манифест (css: ['components/<Name>/styles.css']), и вместе выходила двойная доставка: один и тот же CSS в общем листе и отдельным чанком.

    Второй экземпляр был хуже, чем лишние байты. Он приезжал вне слоёв granum.*, а незаслоённый CSS бьёт любой @layer независимо от специфичности, — то есть стили компонента становились сильнее всей библиотеки, и переопределить их из приложения было нечем.

    Ядро сняло плагин при переезде на granum, спутники остались на старом конфиге. Предупреждение css-double-delivery (INV-CSS-5) этого не поймало: granum смотрит бандл раньше, чем libInjectCss вписывает импорт, — в chunk.code на тот момент его ещё нет.

Changed

  • Веса гранулярных импортов пересчитаны: CSS больше не считается в entry. Стили от этого никуда не делись — их доставляет granum.

v1.0.02026-09-28

Переезд на @feugene/granum 1.0 и первый мажор пакета.

Публичная поверхность не менялась — ломающий тут сам конвейер: peer-зависимость уезжает с @feugene/unocss-preset-granular на @feugene/granum (>=1.0.0 <2.0.0), а приложение переходит с uno.config.ts на granum.config.ts. Версия выровнена с ядром: @feugene/granularity 1.0.0.

Перед обновлением стоит прочитать руководство по переезду в granum — в частности про каскадные слои и сброс браузерных стилей, который теперь нужно импортировать в слой.

Changed

  • yarn doctor is granum doctor --strict, without a wrapper script. scripts/granum-doctor.mjs existed for two reasons and both are gone. It muted token-undefined through the monorepo’s token registry — granum 0.4.0 derives the same verdict from the code itself (a use with a fallback, a token the component assigns itself and dynamicTokens are not findings), so the registry is unnecessary. And it kept recorded debt from failing the gate — that is now --allow=<codes>. Findings across the eight packages went from 861 to 1, and that one is the deliberate !important on the drag cursor in GrTransfer, recorded through --allow.
  • Safelists in the manifests shrank from 3479 entries to 430 (zero in every companion): granum drops entries that static extraction already covers. Nothing in the sources changed and the CSS is byte-for-byte identical — the safelist there is derived from the component’s own class constants, and whether extraction sees a given class is decided by chunking, not by the author.
  • The utility engine changed: @feugene/granum-engine-wind ^0.4.0 instead of @feugene/granum-engine-mini. It vendors preset-wind3 rather than preset-mini, so the vocabulary gained border-collapse, list-none, touch-none, table-fixed and scroll-p* — utilities that existed neither in preset-mini nor in the former extra rules, which is why a class in the markup silently produced no CSS. The package dialect is now unocss/preset-wind3+granum@66, and the peer on the core moved to >=0.3.0 <1.0.0. A consumer swaps the pair in dev dependencies and replaces miniEngine() with windEngine() in granum.config.*.
  • The package is built by @feugene/granum, not by the @feugene/unocss-preset-granular preset. The dist layout and the component entries are driven by the granumProvider({ provider, engine: miniEngine(), entries }) plugin: it builds them from the provider registry, extracts the classes and the consumed tokens by walking the bundle graph, and writes a machine-generated granum.manifest.json next to dist. The package’s own build.lib, granularChunkFileNames and hand-written component entries are gone from vite.config.ts.
  • The manifest is exported as ./granum.manifest.json. An application resolves it through exactly that subpath — without the export the package’s provider cannot be wired up. granum never scans node_modules: the component classes are computed when the package is built.
  • The peer changed: @feugene/granum >=0.2.0 <1.0.0 instead of the preset. The utility engine comes from the application (@feugene/granum-engine-mini sits in the package’s dev dependencies), while the package declares a vocabulary dialect in the manifest — unocss/preset-mini+granum@66, the vocabulary its component classes are written against. An application running an engine of a different vocabulary gets provider-dialect-mismatch and every lost class listed by name instead of silently half-drawn components.
  • The descriptor contract was renamed without a change of meaning. defineGranularComponent → defineGranumComponent, defineGranularProvider → defineGranumProvider, imported from @feugene/granum/contract. Donors are declared as strings (dependencies: ['@feugene/granularity']) rather than instances: an instance would pull the donor into the graph in object form and make the application scan its dist instead of reading the manifest. packageBaseUrl is gone — the manifest’s directory is the base — so granular-provider/node is now a plain alias of the browser entry.
  • granular.options.mjs was replaced by granum.config.mjs, and yarn doctor runs granum doctor against the package’s manifests.
  • Helpers shared by several components moved to src/components/shared/. An import from another component’s directory counts as a declared edge, and declaring it would make a consumer who picked one component pay for the other’s CSS and safelist in full. The public surface is unchanged: the re-exports from the previous paths are still there.

v0.2.02026-09-01

Added

  • --gr-code-editor-placeholder — hook token for the empty-editor hint colour.

  • grCode.diff.lineAdded / grCode.diff.lineRemoved in all three locales.

Fixed

  • The editor placeholder failed AA contrast in both themes. grTheme styled the background, caret, selection, active line and gutters but left .cm-placeholder to CodeMirror’s built-in #888: 3.2:1 on the light surface and 2.9:1 on the dark one, against the 4.5:1 threshold. It now reads --gr-code-editor-placeholder, defaulting to --gr-muted-fg — 5.7:1 and 5.0:1.

    Nothing caught it because the showcase page was outside the axe sweep: the package was never wired into apps/showcase/e2e/components.ts, so GrCodeBlock, GrCodeEditor and GrDiff were scanned by neither axe nor the visual layer. The sweep now covers them.

  • GrCodeEditor: a failed validation moved the form to the editor without putting the caret in it. GrForm finds the control of a field by selector — input, select, textarea, button, [tabindex]:not([tabindex="-1"]) — and that is how both scrollToField and the focus-first-error path work. A contenteditable node is focusable without tabindex, but it does not match that selector, so the form found nothing inside the field at all. .cm-content now carries tabindex="0", on the same node that carries the role.

  • GrDiff: added and removed lines are no longer distinguished by colour alone. The row tone carried the whole message: the +/− sign next to it is aria-hidden, deliberately, so that a screen reader would not read “plus” before every line. The side effect was that it read nothing at all — added, removed and unchanged lines came out identical, and a diff that cannot say what changed is not a diff. Changed lines now carry a visually hidden label (added / removed, translated) in both layouts; context lines stay silent so the marker does not appear on every line of the file. Axe never caught this — roles and contrast were fine all along.

v0.1.12026-08-31

Fixed

  • The peer floor on the core is >=0.41.0, not >=0.40.0. GrCodeBlock left the core in 0.41.0, so with 0.40.0 installed the component would arrive twice — once from the core barrel and once from here, with two granular providers declaring the same name. The floor now states what the package actually needs.

Более ранние версии

Тела этих релизов не показываются: лента целиком весит больше, чем страница имеет право весить. Файл в репозитории всегда полон.

  • v0.1.02026-08-31

CHANGELOG пакета целиком