{"id":24755227,"url":"https://github.com/gravity-ui/page-constructor","last_synced_at":"2026-04-27T15:01:26.775Z","repository":{"id":60707908,"uuid":"531888464","full_name":"gravity-ui/page-constructor","owner":"gravity-ui","description":"A library for rendering web pages or their parts from JSON data.","archived":false,"fork":false,"pushed_at":"2026-04-27T12:06:51.000Z","size":203367,"stargazers_count":64,"open_issues_count":36,"forks_count":23,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-04-27T12:26:56.378Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gravity-ui.png","metadata":{"files":{"readme":"README-ru.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-09-02T10:56:06.000Z","updated_at":"2026-04-27T11:20:14.000Z","dependencies_parsed_at":"2026-01-28T16:01:29.183Z","dependency_job_id":"8c63072d-ae5e-4db8-9bd5-95e7ba00c612","html_url":"https://github.com/gravity-ui/page-constructor","commit_stats":{"total_commits":759,"total_committers":19,"mean_commits":39.94736842105263,"dds":0.691699604743083,"last_synced_commit":"01bb8ff2691b1d90c32dc2109089c70ab7ce1a6a"},"previous_names":[],"tags_count":541,"template":false,"template_full_name":null,"purl":"pkg:github/gravity-ui/page-constructor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gravity-ui%2Fpage-constructor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gravity-ui%2Fpage-constructor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gravity-ui%2Fpage-constructor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gravity-ui%2Fpage-constructor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gravity-ui","download_url":"https://codeload.github.com/gravity-ui/page-constructor/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gravity-ui%2Fpage-constructor/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32341455,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T23:26:28.701Z","status":"online","status_checked_at":"2026-04-27T02:00:06.769Z","response_time":128,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-28T12:37:29.293Z","updated_at":"2026-04-27T15:01:26.768Z","avatar_url":"https://github.com/gravity-ui.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @gravity-ui/page-constructor \u0026middot; [![npm package](https://img.shields.io/npm/v/@gravity-ui/page-constructor)](https://www.npmjs.com/package/@gravity-ui/page-constructor) [![CI](https://img.shields.io/github/actions/workflow/status/gravity-ui/page-constructor/ci.yml?branch=main\u0026label=CI)](https://github.com/gravity-ui/page-constructor/actions/workflows/ci.yml?query=branch:main) [![Release](https://img.shields.io/github/actions/workflow/status/gravity-ui/page-constructor/release.yml?branch=main\u0026label=Release)](https://github.com/gravity-ui/page-constructor/actions/workflows/release.yml?query=branch:main) [![storybook](https://img.shields.io/badge/Storybook-deployed-ff4685)](https://preview.gravity-ui.com/page-constructor/)\n\n## Page constructor\n\n`Page-constructor` (конструктор страниц) — это библиотека, которая позволяет отрисовывать веб-страницы или их части на основе данных в формате `JSON` (в дальнейшем будет добавлена поддержка формата `YAML`).\n\nПри создании страниц используется компонентный подход: страница составляется из набора готовых блоков, которые могут быть расположены в произвольном порядке. Каждому блоку соответствует определенный тип и набор параметров во входных данных.\n\nФормат входных данных и список доступных блоков можно посмотреть в [документации](https://preview.gravity-ui.com/page-constructor/?path=/docs/documentation-blocks--docs).\n\n## Установка\n\n```shell\nnpm install @gravity-ui/page-constructor\n```\n\n## Быстрый старт\n\nДля начала нам понадобится проект на react и какой-нибудь сервер. Например, можно сделать react проект с использованием Vite и сервер на express или можно создать Next.js приложение - в нем сразу будет клиентская и серверная часть.\n\nУстанавливаем необходимые зависимости:\n\n```shell\nnpm install @gravity-ui/page-constructor @diplodoc/transform @gravity-ui/uikit\n```\n\nПодключаем `PageConstructor` на страницу. Для корректной работы его необходимо обернуть в `PageConstructorProvider`:\n\n```tsx\nimport {PageConstructor, PageConstructorProvider} from '@gravity-ui/page-constructor';\nimport '@gravity-ui/page-constructor/styles/styles.scss';\n\nconst App = () =\u003e {\n  const content = {\n    blocks: [\n      {\n        type: 'header-block',\n        title: 'Hello world',\n        background: {color: '#f0f0f0'},\n        description:\n          '**Congratulations!** Have you built a [page-constructor](https://github.com/gravity-ui/page-constructor) into your website',\n      },\n    ],\n  };\n\n  return (\n    \u003cPageConstructorProvider\u003e\n      \u003cPageConstructor content={content} /\u003e\n    \u003c/PageConstructorProvider\u003e\n  );\n};\n\nexport default App;\n```\n\nЭто был самый простой пример подключения. Чтобы заработала YFM разметка, нужно обрабатывать content на сервере и получать его на клиенте.\n\nЕсли ваш сервер это отдельное приложение, то нужно установить page-constructor:\n\n```shell\nnpm install @gravity-ui/page-constructor\n```\n\nДля обработки YFM во всех базовых блоках вызовите `contentTransformer` и передайте туда контент и опции:\n\n```ts\nconst express = require('express');\nconst app = express();\nconst {contentTransformer} = require('@gravity-ui/page-constructor/server');\n\nconst content = {\n  blocks: [\n    {\n      type: 'header-block',\n      title: 'Hello world',\n      background: {color: '#f0f0f0'},\n      description:\n        '**Congratulations!** Have you built a [page-constructor](https://github.com/gravity-ui/page-constructor) into your website',\n    },\n  ],\n};\n\napp.get('/content', (req, res) =\u003e {\n  res.send({content: contentTransformer({content, options: {lang: 'en'}})});\n});\n\napp.listen(3000);\n```\n\nНа клиенте добавляем вызов эндпоинта для получения контента:\n\n```tsx\nimport {PageConstructor, PageConstructorProvider} from '@gravity-ui/page-constructor';\nimport '@gravity-ui/page-constructor/styles/styles.scss';\nimport {useEffect, useState} from 'react';\n\nconst App = () =\u003e {\n  const [content, setContent] = useState();\n\n  useEffect(() =\u003e {\n    (async () =\u003e {\n      const response = await fetch('http://localhost:3000/content').then((r) =\u003e r.json());\n      setContent(response.content);\n    })();\n  }, []);\n\n  return (\n    \u003cPageConstructorProvider\u003e\n      \u003cPageConstructor content={content} /\u003e\n    \u003c/PageConstructorProvider\u003e\n  );\n};\n\nexport default App;\n```\n\n### Готовый шаблон\n\nЧтобы начачать новый проект с нуля можно использовать [готовый шаблон на Next.js](https://github.com/gravity-ui/page-constructor-website-template) который мы подготовили.\n\n### Сборщик статических сайтов\n\n[Page Constructor Builder](https://github.com/gravity-ui/page-constructor-builder) - утилита командной строки для создания статических страниц на основе YAML-конфигураций с использованием @gravity-ui/page-constructor\n\n## Документация\n\n### Параметры\n\n```typescript\ninterface PageConstructorProps {\n  content: PageContent; //Blocks data in JSON format.\n  shouldRenderBlock?: ShouldRenderBlock; // A function that is invoked when rendering each block and  lets you set conditions for its display.\n  custom?: Custom; //Custom blocks (see `Customization`).\n  renderMenu?: () =\u003e React.ReactNode; //A function that renders the page menu with navigation (we plan to add rendering for the default menu version).\n  navigation?: NavigationData; // Navigation data for using navigation component in JSON format\n}\n\ninterface PageConstructorProviderProps {\n  isMobile?: boolean; //A flag indicating that the code is executed in mobile mode.\n  locale?: LocaleContextProps; //Info about the language and domain (used when generating and formatting links).\n  location?: Location; //API of the browser or router history, the page URL.\n  analytics?: AnalyticsContextProps; // function to handle analytics event\n\n  ssrConfig?: SSR; //A flag indicating that the code is run on the server side.\n  theme?: 'light' | 'dark'; //Theme to render the page with.\n  mapsContext?: MapsContextType; //Params for map: apikey, type, scriptSrc, nonce\n}\n\nexport interface PageContent extends Animatable {\n  blocks: Block[];\n  menu?: Menu;\n  background?: MediaProps;\n}\n\ninterface Custom {\n  blocks?: CustomItems;\n  subBlocks?: CustomItems;\n  headers?: CustomItems;\n  loadable?: LoadableConfig;\n}\n\ntype ShouldRenderBlock = (block: Block, blockKey: string) =\u003e Boolean;\n\ninterface Location {\n  history?: History;\n  search?: string;\n  hash?: string;\n  pathname?: string;\n  hostname?: string;\n}\n\ninterface Locale {\n  lang?: Lang;\n  tld?: string;\n}\n\ninterface SSR {\n  isServer?: boolean;\n}\n\ninterface NavigationData {\n  logo: NavigationLogo;\n  header: HeaderData;\n}\n\ninterface NavigationLogo {\n  icon: ImageProps;\n  text?: string;\n  url?: string;\n}\n\ninterface HeaderData {\n  leftItems: NavigationItem[];\n  rightItems?: NavigationItem[];\n}\n\ninterface NavigationLogo {\n  icon: ImageProps;\n  text?: string;\n  url?: string;\n}\n```\n\n### Серверные утилиты\n\nПакет включает набор серверных утилит для преобразования контента.\n\n```ts\nconst {fullTransform} = require('@gravity-ui/page-constructor/server');\n\nconst {html} = fullTransform(content, {\n  lang,\n  extractTitle: true,\n  allowHTML: true,\n  path: __dirname,\n  plugins,\n});\n```\n\nДля преобразования Yandex Flavored Markdown в HTML используется пакет `diplodoc/transfrom`, который входит в peer-зависимости.\n\nЭти утилиты можно также использовать в кастомных компонентах или других частях проекта.\n\n```ts\nconst {\n  typografToText,\n  typografToHTML,\n  yfmTransformer,\n} = require('@gravity-ui/page-constructor/server');\n\nconst post = {\n  title: typografToText(title, lang),\n  content: typografToHTML(content, lang),\n  description: yfmTransformer(lang, description, {plugins}),\n};\n```\n\nСписок других доступных утилит можно найти в [этом разделе](https://github.com/gravity-ui/page-constructor/tree/main/src/text-transform).\n\nПодробная инструкция по подготовке данных, использованию кастомных трансформеров находится в [дополнительном разделе документации](./docs/data-preparation.md).\n\n### Пользовательские блоки\n\nКонструктор страниц поддерживает возможность работы с блоками, определенными пользователем в его приложении. Блоки представляют собой обычные React-компоненты.\n\nДля того чтобы передать в конструктор свои блоки, нужно:\n\n1. Создать у себя в приложении блок.\n\n2. В коде создать объект, в котором ключом будет тип блока (строка), а значением – импортированный компонент блока.\n\n3. Передать созданный объект в параметр `custom.blocks`, `custom.headers` или `custom.subBlocks` компонента `PageConstructor` (в `custom.headers` указываются блоки заголовков, которые должны рендериться отдельно над общим контентом).\n\n4. Теперь во входных данных (параметр `content`) можно использовать созданный блок, указав его тип и данные.\n\nДля того чтобы при создании собственных блоков использовать миксины и стилевые переменные конструктора, нужно в своем файле стилей добавить импорт:\n\n```css\n@import '~@gravity-ui/page-constructor/styles/styles.scss';\n```\n\n### Динамически загружаемые блоки\n\nИногда нужно, чтобы блок рендерился на основе загружаемых данных. В таких случаях применяются динамически загружаемые (`loadable`) блоки.\n\nДля того чтобы добавить пользовательские `loadable` блоки, нужно передать в `PageConstructor` свойство `custom.loadable`, в котором ключами являются названия источников данных (строка) для компонента, а значением — объект.\n\n```typescript\nexport interface LoadableConfigItem {\n  fetch: FetchLoadableData; // data loading method\n  component: React.ComponentType; //blog to pass loaded data\n}\n\ntype FetchLoadableData\u003cTData = any\u003e = (blockKey: string) =\u003e Promise\u003cTData\u003e;\n```\n\n### Сетка\n\n`PageConstructor` использует сетку `bootstrap` и ее реализацию на основе React-компонентов, которую можно использовать в проекте (в том числе отдельно от конструктора).\n\nПример использования:\n\n```jsx\nimport {Grid, Row, Col} from '@gravity-ui/page-constructor';\n\nconst Page = ({children}: React.PropsWithChildren\u003cPageProps\u003e) =\u003e (\n  \u003cGrid\u003e\n    \u003cRow\u003e\n      \u003cCol sizes={{lg: 4, sm: 6, all: 12}}\u003e{children}\u003c/Col\u003e\n    \u003c/Row\u003e\n  \u003c/Grid\u003e\n);\n```\n\n### Навигация\n\nЭлемент навигации по страницам также может быть реализован отдельно от конструктора:\n\n```jsx\nimport {Navigation} from '@gravity-ui/page-constructor';\n\nconst Page = ({data, logo}: React.PropsWithChildren\u003cPageProps\u003e) =\u003e \u003cNavigation data={data} logo={logo} /\u003e;\n```\n\n### Блоки\n\nКаждый из блоков представляет собой неделимый верхнеуровневый компонент. Все блоки хранятся в директории `src/units/constructor/blocks`.\n\n### Саб-блоки\n\nСаб-блоки — это компоненты, которые могут использоваться в свойстве `children` основного блока. В конфигурации указывается список дочерних компонентов из саб-блоков, которые после рендеринга будут переданы в блок как `children`.\n\n### Как добавить новый блок в `page-constructor`\n\n1. В директории `src/blocks` или `src/sub-blocks` создайте папку с кодом блока или саб-блока.\n\n2. Добавьте название блока или саб-блока в перечисление `BlockType` или `SubBlockType` и опишите его свойства в файле `src/models/constructor-items/blocks.ts` или `src/models/constructor-items/sub-blocks.ts` по аналогии с уже существующими.\n\n3. Добавьте экспорт блока в файле `src/blocks/index.ts` или саб-блока в файле `src/sub-blocks/index.ts`.\n\n4. Добавьте новый компонент или блок в маппинг в файле `src/constructor-items.ts`.\n\n5. Добавьте валидатор для нового блока:\n\n   - Добавьте файл `schema.ts` в директорию блока или саб-блока. В этом файле опишите валидатор параметров для данного компонента в формате [`json-schema`](http://json-schema.org/).\n   - Экспортируйте его в файл `schema/validators/blocks.ts` или `schema/validators/sub-blocks.ts`.\n   - Добавьте его в `enum` или `selectCases` в файле `schema/index.ts`.\n\n6. В директории блока добавьте файл `README.md` с описанием входных параметров.\n7. В директории блока добавьте демо-Storybook в папку `__stories__`. Весь демо-контент для компонента `Story` помещается в файл `data.json` в соответствующей директории. Компонент `Story` должен принимать тип свойств блока, иначе в Storybook будут отображаться некорректные данные.\n8. Добавьте шаблон данных блока в папку `src/editor/data/templates/`. Имя файла должно соответствовать типу блока.\n9. При необходимости добавьте иконку превью блока в папку `src/editor/data/templates/`. Имя файла должно соответствовать типу блока.\n\n### Темы\n\n`PageConstructor` поддерживает использование тем: для отдельных свойств блоков можно задавать разные значения в зависимости от выбранной в приложении темы.\n\nДля добавления темы в свойство блока:\n\n1. В файле `models/blocks.ts` определите тип нужного свойства блока через обобщение `ThemeSupporting\u003cT\u003e`, где `T` — тип данного свойства.\n\n2. В файле с React-компонентом блока получите значение свойства с темой через хук `getThemedValue` и `useTheme` (примеры можно посмотреть в блоке `MediaBlock.tsx`).\n\n3. Добавьте поддержку темы в валидатор свойства: в файле `schema.ts` блока оберните данное свойство в `withTheme`.\n\n### i18n\n\nБиблиотека `page-constructor` основана на UIKit и работает с ее экземпляром `i18n`. Для настройки интернационализации используйте `configure` из UIKit:\n\n```typescript\nimport {configure} from '@gravity-ui/uikit';\n\nconfigure({\n  lang: 'ru',\n});\n```\n\n### Карты\n\nДля использования карт необходимо указать тип карты, `scriptSrc` и `apiKey` в поле `mapContext` в `PageConstructorProvider`.\n\nДля режима разработки переменные окружения можно определить в файле `.env.development` в корне проекта.\nНапример, `STORYBOOK_GMAP_API_KEY` содержит значение `apiKey` Google Maps.\n\n### Аналитика\n\n#### Инициализация\n\nДля начала работы с аналитикой передайте обработчик в конструктор. Такой обработчик создается на стороне проекта. Он принимает объекты событий `default` и `custom` и будет срабатывать по клику на кнопки, ссылки, элементы навигации и контролы. Так как для обработки всех событий используется один обработчик, при его создании важно учитывать особенности обработки разных типов событий. Для построения сложной логики предусмотрены предопределенные поля.\n\nДля автоматического запуска настроенных событий передайте `autoEvents: true` в конструктор.\n\n```ts\nfunction sendEvents(events: MyEventType []) {\n  ...\n}\n\n\u003cPageConstructorProvider\n    ...\n\n    analytics={{sendEvents, autoEvents: true}}\n\n    ...\n/\u003e\n```\n\nУ объекта события есть только одно обязательное поле — `name`. Также он включает предопределенные поля для управления сложной логикой. Например, `counter.include` позволяет отправлять событие в конкретный счетчик, если в проекте используются несколько аналитических систем.\n\n```ts\ntype AnalyticsEvent\u003cT = {}\u003e = T \u0026 {\n  name: string;\n  type?: string;\n  counters?: AnalyticsCounters;\n  context?: string;\n};\n```\n\nТип события для проекта можно настроить.\n\n```ts\ntype MyEventType = AnalyticsEvent\u003c{\n  [key: string]?: string; // only a 'string' type is supported\n}\u003e;\n```\n\n#### Селектор счетчика\n\nСобытие можно привязать к конкретной аналитической системе.\n\n```ts\ntype AnalyticsCounters = {\n  include?: string[]; // array of analytics counter ids that will be applied\n  exclude?: string[]; // array of analytics counter ids that will not be applied\n};\n```\n\n#### Параметр `context`\n\nИспользуйте параметр `context` для определения точки вызова события.\n\nИспользуйте предложенный ниже селектор или создайте логику под нужды проекта.\n\n```ts\n// analyticsHandler.ts\nif (isCounterAllowed(counterName, counters)) {\n  analyticsCounter.reachGoal(counterName, name, parameters);\n}\n```\n\n#### Зарезервированные типы событий\n\nРяд предопределенных типов событий применяется для обозначения автоматически настроенных событий. Их можно использовать, например, для фильтрации событий по умолчанию.\n\n```ts\nenum PredefinedEventTypes {\n  Default = 'default-event', // default events which fire on every button click\n  Play = 'play', // React player event\n  Stop = 'stop', // React player event\n}\n```\n\n## Разработка\n\n```bash\nnpm ci\nnpm run dev\n```\n\n### Работа с Vite\n\n```ts\nimport react from '@vitejs/plugin-react-swc';\nimport dynamicImport from 'vite-plugin-dynamic-import';\n\nexport default defineConfig({\n  plugins: [\n    react(),\n    dynamicImport({\n      filter: (id) =\u003e id.includes('/node_modules/@gravity-ui/page-constructor'),\n    }),\n  ],\n});\n```\n\nДля работы с Vite необходимо установить плагин `vite-plugin-dynamic-import` и настроить конфигурацию для поддержки динамических импортов.\n\n## Процесс релиза\n\nВ стандартной практике используются два основных вида коммитов:\n\n1. `Fix` — тип коммита для исправления багов в базе кода (соответствует `PATCH` в семантическом версионировании).\n2. `Feat` — тип коммита для добавления новых функций в базу кода (соответствует `MINOR` в семантическом версионировании).\n3. `BREAKING CHANGE`— тип коммита с подвалом «BREAKING CHANGE:» или знаком «!» после типа/области; указывает на критические изменения в API (соответствует `MAJOR` в семантическом версионировании). Может быть частью любого типа коммита.\n4. Для ручной настройки версии релизного пакета укажите `Release-As: \u003cversion\u003e` в сообщении коммита, например:\n\n```bash\ngit commit -m 'chore: bump release\n\nRelease-As: 1.2.3'\n```\n\nВсю необходимую информацию можно найти [здесь](https://www.conventionalcommits.org/en/v1.0.0/).\n\nПосле того как пулл-реквест (PR) будет одобрен владельцами кода и пройдет все проверки, выполните следующие шаги:\n\n1. Проверьте наличие PR для релиза от робота (например, `chore(main): release 0.0.0`) с изменениями другого контрибьютора. Если такой PR есть, выясните, почему он не был слит. Если контрибьютор согласен на релиз общей версии, переходите к следующему шагу. Если нет, попросите его выпустить свою версию, а затем переходите к следующему шагу.\n2. Объедините свои изменения в один коммит (`squash`) и выполните слияние (`merge`) PR. Важно, чтобы новая версия была выпущена с помощью Github-Actions.\n3. Подождите, пока робот создаст пулл-реквест с новой версией пакета и внесет информацию об изменениях в `CHANGELOG.md`. Следите за процессом на вкладке [**Actions**](https://github.com/gravity-ui/page-constructor/actions).\n4. Проверьте внесенные изменения в `CHANGELOG.md` и одобрите PR робота.\n5. Выполните `squash` и `merge` вашего PR. Следите за процессом релиза на вкладке [**Actions**](https://github.com/gravity-ui/page-constructor/actions).\n\n### Релиз альфа-версий\n\nЕсли необходимо выпустить альфа-версию пакета из ветки, это можно сделать вручную:\n\n1. Перейдите на вкладку **Actions**.\n2. В меню слева выберите рабочий процесс **Release alpha version**.\n3. Справа появится кнопка **Run workflow** с возможностью выбрать ветку.\n4. Рядом будет доступно поле для ручного ввода версии. При первом релизе альфа-версии из ветки это поле можно оставить пустым. Последующие релизы потребуют указания новой версии вручную, так как мы не изменяем `package.json` на случай, если ветка скоро будет удалена. Убедитесь, что в версии используется префикс `alpha`, иначе возникнет ошибка.\n5. Нажмите на кнопку **Run workflow** и дождитесь завершения процесса. Выпускать новые версии можно по мере необходимости, но не слишком часто. В остальных случаях используйте [`npm pack`](https://docs.npmjs.com/cli/v7/commands/npm-pack).\n\n### Релиз бета-версий новой мажорной версии\n\nДля релиза новой стабильной мажорной версии, скорее всего, потребуется сначала выпустить несколько бета-версий. Для этого выполните следующие действия:\n\n1. Создайте или обновите ветку `beta`.\n2. Добавьте необходимые изменения в эту ветку.\n3. При готовности к выпуску новой бета-версии выполните ручной релиз. Для этого создайте пустой коммит или в подвале последнего коммита добавьте следующее сообщение:\n\n   ```bash\n   git commit -m 'fix: last commit\n\n   Release-As: 3.0.0-beta.0' --allow-empty\n   ```\n\n4. После релиза робот создаст новый PR в ветку `beta`, который будет включать обновленный `CHANGELOG.md` и новую версию пакета.\n5. Этот процесс можно повторять неограниченное количество раз. При готовности к выпуску стабильной мажорной версии без бета-метки создайте PR из ветки `beta` в ветку `main`. Следует учесть, что версия пакета будет содержать бета-метку. Система автоматически определит и изменит версию на соответствующую. Например, версия `3.0.0-beta.0` будет преобразована в `3.0.0`.\n\n### Процесс релиза предыдущих мажорных версий\n\nЕсли необходимо выпустить новую версию предыдущей мажорной версии после коммита в `main`, выполните следующие шаги:\n\n1. Обновите ветку, которая относится к предыдущей мажорной версии:\n   1. `version-1.x.x/fixes` — для версии 1.x.x.\n   2. `version-2.x.x` — для версии 2.x.x.\n2. Создайте новую ветку от соответствующей ветки предыдущей мажорной версии.\n3. Выборочно перенесите (`cherry-pick`) свой коммит из ветки `main` в созданную ветку.\n4. Создайте PR и после одобрения слейте его в ветку предыдущей мажорной версии.\n5. Объедините свои изменения в один коммит (`squash`) и выполните слияние (`merge`) PR. Важно, чтобы новая версия была выпущена с помощью Github-Actions.\n6. Подождите, пока робот создаст пулл-реквест с новой версией пакета и внесет информацию об изменениях в `CHANGELOG.md`. Следите за процессом на вкладке [**Actions**](https://github.com/gravity-ui/page-constructor/actions).\n7. Проверьте внесенные изменения в `CHANGELOG.md` и одобрите PR робота.\n8. Выполните `squash` и `merge` вашего PR. Следите за процессом релиза на вкладке [**Actions**](https://github.com/gravity-ui/page-constructor/actions).\n\n## Редактор конструктора страниц\n\nПользовательский интерфейс редактора позволяет управлять содержимым страницы с функцией предпросмотра в реальном времени.\n\nПример использования:\n\n```tsx\nimport {Editor} from '@gravity-ui/page-constructor/editor';\n\ninterface MyAppEditorProps {\n  initialContent: PageContent;\n  transformContent: ContentTransformer;\n  onChange: (content: PageContent) =\u003e void;\n}\n\nexport const MyAppEditor = ({initialContent, onChange, transformContent}: MyAppEditorProps) =\u003e (\n  \u003cEditor content={initialContent} onChange={onChange} transformContent={transformContent} /\u003e\n);\n```\n\n## Memory Bank (Банк памяти)\n\nЭтот проект включает в себя комплексный **Memory Bank** (Банк памяти) — коллекцию файлов документации в формате Markdown, которые предоставляют подробную информацию об архитектуре проекта, компонентах и паттернах использования. Memory Bank особенно полезен при работе с AI-агентами, поскольку содержит структурированную информацию о:\n\n- **Обзор проекта**: Основные требования, цели и контекст\n- **Документация компонентов**: Подробные руководства по использованию всех компонентов\n- **Архитектура системы**: Технические паттерны и проектные решения\n- **Прогресс разработки**: Текущий статус и детали реализации\n\n### Использование Memory Bank\n\nMemory Bank расположен в директории `memory-bank/` и состоит из обычных Markdown-файлов, которые можно читать как любую другую документацию:\n\n- `projectbrief.md` - Основополагающий документ с ключевыми требованиями\n- `productContext.md` - Назначение проекта и цели пользовательского опыта\n- `systemPatterns.md` - Архитектура и технические решения\n- `techContext.md` - Технологии, настройка и ограничения\n- `activeContext.md` - Текущий фокус работы и последние изменения\n- `progress.md` - Статус реализации и известные проблемы\n- `usage/` - Документация по использованию конкретных компонентов\n- `storybookComponents.md` - Детали интеграции со Storybook\n\n### Для AI-агентов\n\nПри работе с AI-агентами над этим проектом Memory Bank служит как комплексная база знаний, которая помогает агентам понять:\n\n- Структуру проекта и паттерны\n- API компонентов и примеры использования\n- Рабочие процессы разработки и лучшие практики\n- Текущий статус реализации и следующие шаги\n\nAI-агенты могут читать эти файлы, чтобы быстро разобраться в контексте проекта и принимать более обоснованные решения относительно изменений кода и реализации.\n\n## Тесты\n\nПолный комплект документации можно найти по [этой ссылке](./test-utils/docs/README.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgravity-ui%2Fpage-constructor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgravity-ui%2Fpage-constructor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgravity-ui%2Fpage-constructor/lists"}