@retailcrm/embed-ui-v1-components 0.9.19 → 0.9.22-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +9 -1
- package/README.md +5 -2
- package/assets/sprites/actions/add-square-outlined.svg +8 -0
- package/assets/sprites/actions/drag.svg +8 -0
- package/bin/embed-ui-v1-components.mjs +231 -46
- package/bin/postinstall.mjs +3 -2
- package/dist/host.cjs +1223 -501
- package/dist/host.css +637 -10
- package/dist/host.d.ts +152 -78
- package/dist/host.js +1224 -502
- package/dist/remote.cjs +1358 -298
- package/dist/remote.d.ts +805 -67
- package/dist/remote.js +1360 -300
- package/docs/AI.md +99 -17
- package/docs/COMPONENTS.md +58 -59
- package/docs/FORMAT.md +10 -10
- package/docs/PROFILES.md +39 -22
- package/docs/README.md +11 -5
- package/docs/profiles/components/UiAddButton.yml +134 -0
- package/docs/profiles/components/UiAlert.yml +105 -0
- package/docs/profiles/components/UiAvatar.yml +88 -0
- package/docs/profiles/{UiAvatarList.yml → components/UiAvatarList.yml} +26 -0
- package/docs/profiles/{UiButton.yml → components/UiButton.yml} +14 -8
- package/docs/profiles/components/UiCalendar.yml +190 -0
- package/docs/profiles/components/UiCheckbox.yml +111 -0
- package/docs/profiles/components/UiCollapse.yml +129 -0
- package/docs/profiles/components/UiCollapseBox.yml +143 -0
- package/docs/profiles/{UiCollapseGroup.yml → components/UiCollapseGroup.yml} +24 -0
- package/docs/profiles/components/UiCopyButton.yml +104 -0
- package/docs/profiles/components/UiDate.yml +84 -0
- package/docs/profiles/components/UiDatePicker.yml +138 -0
- package/docs/profiles/components/UiError.yml +123 -0
- package/docs/profiles/{UiField.yml → components/UiField.yml} +46 -15
- package/docs/profiles/components/UiInfobox.yml +130 -0
- package/docs/profiles/components/UiLink.yml +111 -0
- package/docs/profiles/components/UiLoader.yml +71 -0
- package/docs/profiles/components/UiMenuItem.yml +93 -0
- package/docs/profiles/{UiMenuItemGroup.yml → components/UiMenuItemGroup.yml} +25 -0
- package/docs/profiles/components/UiModalSidebar.yml +156 -0
- package/docs/profiles/components/UiModalWindow.yml +181 -0
- package/docs/profiles/{UiModalWindowSurface.yml → components/UiModalWindowSurface.yml} +30 -0
- package/docs/profiles/components/UiNumberStepper.yml +100 -0
- package/docs/profiles/{UiPageHeader.yml → components/UiPageHeader.yml} +39 -23
- package/docs/profiles/components/UiPopconfirm.yml +164 -0
- package/docs/profiles/{UiPopper.yml → components/UiPopper.yml} +66 -13
- package/docs/profiles/{UiPopperConnector.yml → components/UiPopperConnector.yml} +5 -25
- package/docs/profiles/{UiPopperTarget.yml → components/UiPopperTarget.yml} +5 -25
- package/docs/profiles/components/UiRadio.yml +91 -0
- package/docs/profiles/{UiRadioSwitch.yml → components/UiRadioSwitch.yml} +55 -32
- package/docs/profiles/{UiRadioSwitchOption.yml → components/UiRadioSwitchOption.yml} +7 -13
- package/docs/profiles/components/UiScrollBox.yml +108 -0
- package/docs/profiles/{UiSelect.yml → components/UiSelect.yml} +133 -44
- package/docs/profiles/components/UiSelectOption.yml +74 -0
- package/docs/profiles/components/UiSelectOptionGroup.yml +66 -0
- package/docs/profiles/components/UiSkeleton.yml +82 -0
- package/docs/profiles/components/UiSlider.yml +161 -0
- package/docs/profiles/components/UiSwitch.yml +123 -0
- package/docs/profiles/components/UiTab.yml +234 -0
- package/docs/profiles/{UiTabGroup.yml → components/UiTabGroup.yml} +0 -30
- package/docs/profiles/components/UiTable.yml +622 -0
- package/docs/profiles/{UiTableBodyCell.yml → components/UiTableBodyCell.yml} +26 -0
- package/docs/profiles/components/UiTableColumn.yml +87 -0
- package/docs/profiles/components/UiTableFooterButton.yml +85 -0
- package/docs/profiles/components/UiTableFooterSection.yml +73 -0
- package/docs/profiles/{UiTableHeadCell.yml → components/UiTableHeadCell.yml} +26 -0
- package/docs/profiles/{UiTableSorter.yml → components/UiTableSorter.yml} +27 -0
- package/docs/profiles/components/UiTag.yml +90 -0
- package/docs/profiles/{UiTextbox.yml → components/UiTextbox.yml} +20 -32
- package/docs/profiles/components/UiTimePicker.yml +144 -0
- package/docs/profiles/{UiToggleButton.yml → components/UiToggleButton.yml} +16 -11
- package/docs/profiles/{UiToggleGroup.yml → components/UiToggleGroup.yml} +25 -13
- package/docs/profiles/{UiToggleGroupOption.yml → components/UiToggleGroupOption.yml} +7 -11
- package/docs/profiles/components/UiToolbarButton.yml +87 -0
- package/docs/profiles/components/UiToolbarLink.yml +80 -0
- package/docs/profiles/components/UiTooltip.yml +97 -0
- package/docs/profiles/components/UiTransition.yml +62 -0
- package/docs/profiles/components/UiYandexMap.yml +104 -0
- package/docs/profiles/pages/CardSettingsPage.yml +58 -0
- package/docs/profiles/pages/CollapseBlockPage.yml +46 -0
- package/docs/profiles/pages/EntityListPage.yml +66 -0
- package/docs/profiles/pages/ModalSidebar.yml +158 -0
- package/docs/profiles/pages/ModalWindow.yml +55 -0
- package/docs/profiles/pages/MultiColumnPage.yml +27 -0
- package/docs/profiles/pages/PageComposition.yml +56 -0
- package/package.json +15 -15
- package/docs/profiles/UiAddButton.yml +0 -57
- package/docs/profiles/UiAlert.yml +0 -48
- package/docs/profiles/UiAvatar.yml +0 -48
- package/docs/profiles/UiCalendar.yml +0 -48
- package/docs/profiles/UiCheckbox.yml +0 -53
- package/docs/profiles/UiCollapse.yml +0 -40
- package/docs/profiles/UiCollapseBox.yml +0 -51
- package/docs/profiles/UiCopyButton.yml +0 -52
- package/docs/profiles/UiDate.yml +0 -38
- package/docs/profiles/UiDatePicker.yml +0 -59
- package/docs/profiles/UiError.yml +0 -32
- package/docs/profiles/UiImage.yml +0 -39
- package/docs/profiles/UiInfobox.yml +0 -45
- package/docs/profiles/UiLink.yml +0 -51
- package/docs/profiles/UiLoader.yml +0 -38
- package/docs/profiles/UiMenuItem.yml +0 -57
- package/docs/profiles/UiModalSidebar.yml +0 -46
- package/docs/profiles/UiModalWindow.yml +0 -44
- package/docs/profiles/UiNumberStepper.yml +0 -52
- package/docs/profiles/UiRadio.yml +0 -38
- package/docs/profiles/UiScrollBox.yml +0 -31
- package/docs/profiles/UiSelectOption.yml +0 -44
- package/docs/profiles/UiSelectOptionGroup.yml +0 -38
- package/docs/profiles/UiSkeleton.yml +0 -41
- package/docs/profiles/UiSlider.yml +0 -38
- package/docs/profiles/UiSwitch.yml +0 -37
- package/docs/profiles/UiTab.yml +0 -119
- package/docs/profiles/UiTable.yml +0 -152
- package/docs/profiles/UiTableColumn.yml +0 -50
- package/docs/profiles/UiTableFooterButton.yml +0 -44
- package/docs/profiles/UiTableFooterSection.yml +0 -38
- package/docs/profiles/UiTag.yml +0 -41
- package/docs/profiles/UiTimePicker.yml +0 -46
- package/docs/profiles/UiToolbarButton.yml +0 -37
- package/docs/profiles/UiToolbarLink.yml +0 -32
- package/docs/profiles/UiTooltip.yml +0 -43
- package/docs/profiles/UiTransition.yml +0 -27
- package/docs/profiles/UiYandexMap.yml +0 -29
package/AGENTS.md
CHANGED
|
@@ -77,7 +77,7 @@ Commonly used exports from `remote` include:
|
|
|
77
77
|
|
|
78
78
|
- Do not import from `@retailcrm/embed-ui-v1-components/host` in normal extension code.
|
|
79
79
|
- Do not rely on internal file paths from this repository.
|
|
80
|
-
- Do not treat
|
|
80
|
+
- Do not treat examples or internal source layout as stable runtime API.
|
|
81
81
|
- Do not assume every host-side component is available to extension authors.
|
|
82
82
|
|
|
83
83
|
## Example
|
|
@@ -122,5 +122,13 @@ const save = () => {}
|
|
|
122
122
|
[`./docs/README.md`](./docs/README.md)
|
|
123
123
|
- Machine-oriented package summary:
|
|
124
124
|
[`./docs/AI.md`](./docs/AI.md)
|
|
125
|
+
- Page composition guidelines:
|
|
126
|
+
[`./docs/profiles/pages`](./docs/profiles/pages)
|
|
125
127
|
- Component profiles:
|
|
126
128
|
[`./docs/PROFILES.md`](./docs/PROFILES.md)
|
|
129
|
+
|
|
130
|
+
For table, catalog, registry, journal, or search-result screens, read [`./docs/AI.md`](./docs/AI.md)
|
|
131
|
+
and [`./docs/profiles/pages/EntityListPage.yml`](./docs/profiles/pages/EntityListPage.yml), then check the
|
|
132
|
+
`UiTable` and `UiLink` profiles before generating code. Put filters above the table, persist
|
|
133
|
+
filters and pagination in GET query parameters when routing exists, and set `size="small"` on
|
|
134
|
+
`UiLink` inside table cells by default.
|
package/README.md
CHANGED
|
@@ -46,15 +46,18 @@ import { UiButton } from '@retailcrm/embed-ui-v1-components/remote'
|
|
|
46
46
|
|
|
47
47
|
Дополнительные материалы по пакету находятся в `docs/`:
|
|
48
48
|
|
|
49
|
+
- [`AGENTS.md`](./AGENTS.md) — инструкции для AI-агентов, использующих пакет в целевом проекте.
|
|
49
50
|
- [`docs/README.md`](./docs/README.md) — обзор пакета и правил использования.
|
|
50
51
|
- [`docs/COMPONENTS.md`](./docs/COMPONENTS.md) — карта публичных компонентов.
|
|
51
52
|
- [`docs/AI.md`](./docs/AI.md) — контекст для ИИ и автоматизаций.
|
|
52
|
-
- [`docs/PROFILES.md`](./docs/PROFILES.md) — AI-friendly YAML-профили
|
|
53
|
+
- [`docs/PROFILES.md`](./docs/PROFILES.md) — AI-friendly YAML-профили компонентов и страниц.
|
|
53
54
|
- [`docs/FORMAT.md`](./docs/FORMAT.md) — формат описания компонента для AI-агентов.
|
|
55
|
+
- [`docs/profiles/pages`](./docs/profiles/pages) — YAML-профили страниц, модалок, шторок, фильтров и таблиц.
|
|
54
56
|
|
|
55
57
|
## AI и инициализация `AGENTS.md`
|
|
56
58
|
|
|
57
|
-
После установки пакет показывает подсказку, что внутри есть
|
|
59
|
+
После установки пакет показывает подсказку, что внутри есть `README.md`, `AGENTS.md`,
|
|
60
|
+
AI-заметки и YAML-профили компонентов и страниц.
|
|
58
61
|
|
|
59
62
|
Если в целевом проекте еще нет `AGENTS.md`, можно сгенерировать стартовый файл командой:
|
|
60
63
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path
|
|
3
|
+
fill-rule="evenodd"
|
|
4
|
+
clip-rule="evenodd"
|
|
5
|
+
fill="currentColor"
|
|
6
|
+
d="M19 3H5C3.89543 3 3 3.89543 3 5V19C3 20.1046 3.89543 21 5 21H19C20.1046 21 21 20.1046 21 19V5C21 3.89543 20.1046 3 19 3ZM19 19H5V5H19V19ZM11 13H8.5C8.22386 13 8 12.7761 8 12.5V11.5C8 11.2239 8.22386 11 8.5 11H11V8.5C11 8.22386 11.2239 8 11.5 8H12.5C12.7761 8 13 8.22386 13 8.5V11H15.5C15.7761 11 16 11.2239 16 11.5V12.5C16 12.7761 15.7761 13 15.5 13H13V15.5C13 15.7761 12.7761 16 12.5 16H11.5C11.2239 16 11 15.7761 11 15.5V13Z"
|
|
7
|
+
/>
|
|
8
|
+
</svg>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" >
|
|
2
|
+
<path
|
|
3
|
+
d="M7.4987 6.66683C8.41917 6.66683 9.16536 5.92064 9.16536 5.00016C9.16536 4.07969 8.41917 3.3335 7.4987 3.3335C6.57822 3.3335 5.83203 4.07969 5.83203 5.00016C5.83203 5.92064 6.57822 6.66683 7.4987 6.66683ZM5.83203 10.0002C5.83203 9.07969 6.57822 8.3335 7.4987 8.3335C8.41917 8.3335 9.16536 9.07969 9.16536 10.0002C9.16536 10.9206 8.41917 11.6668 7.4987 11.6668C6.57822 11.6668 5.83203 10.9206 5.83203 10.0002ZM7.4987 13.3335C6.57822 13.3335 5.83203 14.0797 5.83203 15.0002C5.83203 15.9206 6.57822 16.6668 7.4987 16.6668C8.41917 16.6668 9.16536 15.9206 9.16536 15.0002C9.16536 14.0797 8.41917 13.3335 7.4987 13.3335ZM14.1654 5.00016C14.1654 5.92064 13.4192 6.66683 12.4987 6.66683C11.5782 6.66683 10.832 5.92064 10.832 5.00016C10.832 4.07969 11.5782 3.3335 12.4987 3.3335C13.4192 3.3335 14.1654 4.07969 14.1654 5.00016ZM12.4987 8.3335C11.5782 8.3335 10.832 9.07969 10.832 10.0002C10.832 10.9206 11.5782 11.6668 12.4987 11.6668C13.4192 11.6668 14.1654 10.9206 14.1654 10.0002C14.1654 9.07969 13.4192 8.3335 12.4987 8.3335ZM10.832 15.0002C10.832 14.0797 11.5782 13.3335 12.4987 13.3335C13.4192 13.3335 14.1654 14.0797 14.1654 15.0002C14.1654 15.9206 13.4192 16.6668 12.4987 16.6668C11.5782 16.6668 10.832 15.9206 10.832 15.0002Z"
|
|
4
|
+
fill="currentColor"
|
|
5
|
+
fill-rule="evenodd"
|
|
6
|
+
clip-rule="evenodd"
|
|
7
|
+
/>
|
|
8
|
+
</svg>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
3
4
|
import fs from 'node:fs'
|
|
4
5
|
import path from 'node:path'
|
|
5
6
|
import process from 'node:process'
|
|
@@ -7,6 +8,8 @@ import process from 'node:process'
|
|
|
7
8
|
const PACKAGE_NAME = '@retailcrm/embed-ui-v1-components'
|
|
8
9
|
const DEFAULT_NEWLINE = '\n'
|
|
9
10
|
const AGENTS_SECTION_HEADER = '## @retailcrm/embed-ui-v1-components'
|
|
11
|
+
const AGENTS_SECTION_START = '<!-- embed-ui-agents:start -->'
|
|
12
|
+
const AGENTS_SECTION_END = '<!-- embed-ui-agents:end -->'
|
|
10
13
|
|
|
11
14
|
const HELP_TEXT = `Usage:
|
|
12
15
|
npx ${PACKAGE_NAME} init-agents [target] [options]
|
|
@@ -21,6 +24,136 @@ Examples:
|
|
|
21
24
|
npx ${PACKAGE_NAME} init-agents --force
|
|
22
25
|
`
|
|
23
26
|
|
|
27
|
+
const toPosixPath = (value) => value.split(path.sep).join('/')
|
|
28
|
+
|
|
29
|
+
const withDotPrefix = (value) => {
|
|
30
|
+
if (!value || value === '.') {
|
|
31
|
+
return '.'
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return value.startsWith('.') ? value : `./${value}`
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const isPackageRoot = (directory) => {
|
|
38
|
+
const packageJsonPath = path.join(directory, 'package.json')
|
|
39
|
+
|
|
40
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
41
|
+
return false
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
|
|
46
|
+
|
|
47
|
+
return packageJson.name === PACKAGE_NAME
|
|
48
|
+
} catch {
|
|
49
|
+
return false
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const isInsideDirectory = (parent, child) => {
|
|
54
|
+
const relativePath = path.relative(parent, child)
|
|
55
|
+
|
|
56
|
+
return relativePath === '' || (!relativePath.startsWith('..') && !path.isAbsolute(relativePath))
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const addNestedPackageCandidates = (start, addCandidate) => {
|
|
60
|
+
const packagePath = path.join('node_modules', ...PACKAGE_NAME.split('/'))
|
|
61
|
+
const ignoredDirectories = new Set(['.git', '.yarn', 'dist', 'node_modules'])
|
|
62
|
+
const queue = [path.resolve(start)]
|
|
63
|
+
const seen = new Set(queue)
|
|
64
|
+
|
|
65
|
+
for (let index = 0; index < queue.length; index++) {
|
|
66
|
+
const current = queue[index]
|
|
67
|
+
|
|
68
|
+
addCandidate(path.join(current, packagePath))
|
|
69
|
+
|
|
70
|
+
let entries = []
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
entries = fs.readdirSync(current, { withFileTypes: true })
|
|
74
|
+
} catch {
|
|
75
|
+
continue
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
for (const entry of entries) {
|
|
79
|
+
if (!entry.isDirectory() || entry.name.startsWith('.') || ignoredDirectories.has(entry.name)) {
|
|
80
|
+
continue
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const next = path.join(current, entry.name)
|
|
84
|
+
|
|
85
|
+
if (!seen.has(next)) {
|
|
86
|
+
seen.add(next)
|
|
87
|
+
queue.push(next)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const getCurrentPackageRoot = () => {
|
|
94
|
+
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
|
|
95
|
+
|
|
96
|
+
return isPackageRoot(packageRoot) ? packageRoot : null
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const findPackageRoot = (target) => {
|
|
100
|
+
const candidates = []
|
|
101
|
+
const seen = new Set()
|
|
102
|
+
|
|
103
|
+
const addCandidate = (candidate) => {
|
|
104
|
+
const resolved = path.resolve(candidate)
|
|
105
|
+
|
|
106
|
+
if (!seen.has(resolved)) {
|
|
107
|
+
seen.add(resolved)
|
|
108
|
+
candidates.push(resolved)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const addNodeModulesCandidates = (start) => {
|
|
113
|
+
const packagePath = path.join('node_modules', ...PACKAGE_NAME.split('/'))
|
|
114
|
+
let current = path.resolve(start)
|
|
115
|
+
|
|
116
|
+
while (true) {
|
|
117
|
+
addCandidate(path.join(current, packagePath))
|
|
118
|
+
|
|
119
|
+
const parent = path.dirname(current)
|
|
120
|
+
|
|
121
|
+
if (parent === current) {
|
|
122
|
+
break
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
current = parent
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
addCandidate(target)
|
|
130
|
+
addNodeModulesCandidates(target)
|
|
131
|
+
addNestedPackageCandidates(target, addCandidate)
|
|
132
|
+
|
|
133
|
+
const currentPackageRoot = getCurrentPackageRoot()
|
|
134
|
+
|
|
135
|
+
if (currentPackageRoot && isInsideDirectory(target, currentPackageRoot)) {
|
|
136
|
+
addCandidate(currentPackageRoot)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const packageRoot = candidates.find(isPackageRoot)
|
|
140
|
+
|
|
141
|
+
if (!packageRoot) {
|
|
142
|
+
throw new Error(
|
|
143
|
+
`Cannot find local ${PACKAGE_NAME}. Install it in this project or run init-agents from the package workspace.`
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return packageRoot
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const createPackageDocsPath = (target) => {
|
|
151
|
+
const packageRoot = findPackageRoot(target)
|
|
152
|
+
const relativePath = path.relative(target, packageRoot)
|
|
153
|
+
|
|
154
|
+
return withDotPrefix(toPosixPath(relativePath))
|
|
155
|
+
}
|
|
156
|
+
|
|
24
157
|
const parseArgs = (argv) => {
|
|
25
158
|
const options = {
|
|
26
159
|
command: null,
|
|
@@ -67,83 +200,134 @@ const parseArgs = (argv) => {
|
|
|
67
200
|
return options
|
|
68
201
|
}
|
|
69
202
|
|
|
70
|
-
const createAgentsTemplate = () => {
|
|
203
|
+
const createAgentsTemplate = (packageDocsPath) => {
|
|
71
204
|
return `# AGENTS.md
|
|
72
205
|
|
|
206
|
+
${createAgentsSection(packageDocsPath)}`
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const createAgentsSection = (packageDocsPath) => {
|
|
210
|
+
return `${AGENTS_SECTION_START}
|
|
73
211
|
${AGENTS_SECTION_HEADER}
|
|
74
212
|
|
|
75
213
|
When working with \`${PACKAGE_NAME}\` in this project:
|
|
76
214
|
|
|
77
|
-
1. Read
|
|
78
|
-
2. Then read
|
|
79
|
-
3. Then
|
|
80
|
-
4.
|
|
81
|
-
5.
|
|
215
|
+
1. Read \`${packageDocsPath}/README.md\`.
|
|
216
|
+
2. Then read \`${packageDocsPath}/AGENTS.md\`.
|
|
217
|
+
3. Then read \`${packageDocsPath}/docs/AI.md\`.
|
|
218
|
+
4. Then read \`${packageDocsPath}/docs/COMPONENTS.md\`.
|
|
219
|
+
5. Then read \`${packageDocsPath}/docs/PROFILES.md\`.
|
|
220
|
+
6. Then open relevant component profiles from \`${packageDocsPath}/docs/profiles/components/*.yml\`.
|
|
221
|
+
7. For complete pages, modals, sidebars, filters, tables, or settings layouts, open the relevant
|
|
222
|
+
page profile from \`${packageDocsPath}/docs/profiles/pages/*.yml\`.
|
|
223
|
+
8. Prefer those docs and profiles over guessing from internal implementation files.
|
|
224
|
+
9. Import only from documented public entrypoints:
|
|
82
225
|
- \`${PACKAGE_NAME}/remote\`
|
|
83
226
|
- \`${PACKAGE_NAME}/host\`
|
|
84
227
|
- \`${PACKAGE_NAME}/assets/...\`
|
|
85
|
-
|
|
86
|
-
|
|
228
|
+
10. Prefer \`${PACKAGE_NAME}/remote\` for extension UI code.
|
|
229
|
+
11. Do not import from package-internal files such as \`dist/*\`, repository-only paths, or source internals.
|
|
87
230
|
|
|
88
231
|
## Suggested Reading Order
|
|
89
232
|
|
|
90
|
-
1. \`
|
|
91
|
-
2. \`
|
|
92
|
-
3.
|
|
93
|
-
4. \`docs/
|
|
94
|
-
5.
|
|
95
|
-
|
|
233
|
+
1. \`README.md\`
|
|
234
|
+
2. \`AGENTS.md\`
|
|
235
|
+
3. \`docs/AI.md\`
|
|
236
|
+
4. \`docs/COMPONENTS.md\`
|
|
237
|
+
5. \`docs/PROFILES.md\`
|
|
238
|
+
6. The relevant component profile from \`docs/profiles/components/*.yml\`
|
|
239
|
+
7. The relevant page profile from \`docs/profiles/pages/*.yml\` for full-screen or overlay composition
|
|
240
|
+
8. \`docs/FORMAT.md\` if you need to understand profile structure
|
|
241
|
+
9. Public type declarations only when no profile exists yet
|
|
242
|
+
${AGENTS_SECTION_END}
|
|
243
|
+
`
|
|
96
244
|
}
|
|
97
245
|
|
|
98
|
-
const
|
|
99
|
-
|
|
246
|
+
const findMarkedSectionRange = (content) => {
|
|
247
|
+
const start = content.indexOf(AGENTS_SECTION_START)
|
|
248
|
+
const end = content.indexOf(AGENTS_SECTION_END, start + AGENTS_SECTION_START.length)
|
|
100
249
|
|
|
101
|
-
|
|
250
|
+
if (start === -1 && end === -1) {
|
|
251
|
+
return null
|
|
252
|
+
}
|
|
102
253
|
|
|
103
|
-
1
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
4. Prefer those docs and profiles over guessing from internal implementation files.
|
|
107
|
-
5. Import only from documented public entrypoints:
|
|
108
|
-
- \`${PACKAGE_NAME}/remote\`
|
|
109
|
-
- \`${PACKAGE_NAME}/host\`
|
|
110
|
-
- \`${PACKAGE_NAME}/assets/...\`
|
|
111
|
-
6. Prefer \`${PACKAGE_NAME}/remote\` for extension UI code.
|
|
112
|
-
7. Do not import from package-internal files such as \`dist/*\`, repository-only paths, or source internals.
|
|
254
|
+
if (start === -1 || end === -1 || end < start) {
|
|
255
|
+
throw new Error(`AGENTS.md contains incomplete ${PACKAGE_NAME} section markers`)
|
|
256
|
+
}
|
|
113
257
|
|
|
114
|
-
|
|
258
|
+
return {
|
|
259
|
+
start,
|
|
260
|
+
end: end + AGENTS_SECTION_END.length,
|
|
261
|
+
}
|
|
262
|
+
}
|
|
115
263
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
264
|
+
const findLegacySectionRange = (content) => {
|
|
265
|
+
const escapedHeader = AGENTS_SECTION_HEADER.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
266
|
+
const headerPattern = new RegExp(`(^|\\n)${escapedHeader}(?=\\n|$)`, 'u')
|
|
267
|
+
const match = headerPattern.exec(content)
|
|
268
|
+
|
|
269
|
+
if (!match) {
|
|
270
|
+
return null
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const start = match.index + match[1].length
|
|
274
|
+
const afterHeader = content.slice(start + AGENTS_SECTION_HEADER.length)
|
|
275
|
+
const nextExternalHeading = /\n## (?!Suggested Reading Order\b)[^\n]*/u.exec(afterHeader)
|
|
276
|
+
|
|
277
|
+
return {
|
|
278
|
+
start,
|
|
279
|
+
end: nextExternalHeading
|
|
280
|
+
? start + AGENTS_SECTION_HEADER.length + nextExternalHeading.index
|
|
281
|
+
: content.length,
|
|
282
|
+
}
|
|
122
283
|
}
|
|
123
284
|
|
|
124
|
-
const hasPackageSection = (content) =>
|
|
285
|
+
const hasPackageSection = (content) => {
|
|
286
|
+
return Boolean(findMarkedSectionRange(content) || findLegacySectionRange(content))
|
|
287
|
+
}
|
|
125
288
|
|
|
126
289
|
const appendSection = (content, section) => {
|
|
127
290
|
const trimmed = content.replace(/\s+$/u, '')
|
|
128
291
|
|
|
129
292
|
if (!trimmed.length) {
|
|
130
|
-
return `${section}${DEFAULT_NEWLINE}`
|
|
293
|
+
return `${section.trimEnd()}${DEFAULT_NEWLINE}`
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return `${trimmed}${DEFAULT_NEWLINE}${DEFAULT_NEWLINE}${section.trimEnd()}${DEFAULT_NEWLINE}`
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const replaceRange = (content, range, section) => {
|
|
300
|
+
const before = content.slice(0, range.start).replace(/\s+$/u, '')
|
|
301
|
+
const after = content.slice(range.end).replace(/^\s+/u, '')
|
|
302
|
+
const parts = []
|
|
303
|
+
|
|
304
|
+
if (before) {
|
|
305
|
+
parts.push(before)
|
|
131
306
|
}
|
|
132
307
|
|
|
133
|
-
|
|
308
|
+
parts.push(section.trimEnd())
|
|
309
|
+
|
|
310
|
+
if (after) {
|
|
311
|
+
parts.push(after)
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return `${parts.join(`${DEFAULT_NEWLINE}${DEFAULT_NEWLINE}`)}${DEFAULT_NEWLINE}`
|
|
134
315
|
}
|
|
135
316
|
|
|
136
317
|
const replaceSection = (content, section) => {
|
|
137
|
-
const
|
|
138
|
-
|
|
318
|
+
const markedRange = findMarkedSectionRange(content)
|
|
319
|
+
|
|
320
|
+
if (markedRange) {
|
|
321
|
+
return replaceRange(content, markedRange, section)
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const legacyRange = findLegacySectionRange(content)
|
|
139
325
|
|
|
140
|
-
if (
|
|
141
|
-
return
|
|
326
|
+
if (legacyRange) {
|
|
327
|
+
return replaceRange(content, legacyRange, section)
|
|
142
328
|
}
|
|
143
329
|
|
|
144
|
-
return content
|
|
145
|
-
.replace(sectionPattern, section.trimEnd())
|
|
146
|
-
.replace(/\s+$/u, '') + DEFAULT_NEWLINE
|
|
330
|
+
return appendSection(content, section)
|
|
147
331
|
}
|
|
148
332
|
|
|
149
333
|
const initAgents = (target, force) => {
|
|
@@ -158,10 +342,11 @@ const initAgents = (target, force) => {
|
|
|
158
342
|
}
|
|
159
343
|
|
|
160
344
|
const agentsPath = path.join(target, 'AGENTS.md')
|
|
161
|
-
const
|
|
345
|
+
const packageDocsPath = createPackageDocsPath(target)
|
|
346
|
+
const section = createAgentsSection(packageDocsPath)
|
|
162
347
|
|
|
163
348
|
if (!fs.existsSync(agentsPath)) {
|
|
164
|
-
fs.writeFileSync(agentsPath, createAgentsTemplate(), 'utf8')
|
|
349
|
+
fs.writeFileSync(agentsPath, createAgentsTemplate(packageDocsPath), 'utf8')
|
|
165
350
|
|
|
166
351
|
console.log(`AGENTS.md was created at ${agentsPath}`)
|
|
167
352
|
console.log('Next step: review it and adjust project-specific rules if needed.')
|
package/bin/postinstall.mjs
CHANGED
|
@@ -26,8 +26,9 @@ const agentsPath = path.join(targetRoot, 'AGENTS.md')
|
|
|
26
26
|
const hasAgentsFile = fs.existsSync(agentsPath)
|
|
27
27
|
|
|
28
28
|
console.log('')
|
|
29
|
-
console.log(`[${PACKAGE_NAME}] AI docs are available in node_modules/${PACKAGE_NAME}/docs`)
|
|
30
|
-
console.log(`[${PACKAGE_NAME}] Start with docs/AI.md, docs/COMPONENTS.md, and docs/
|
|
29
|
+
console.log(`[${PACKAGE_NAME}] AI docs are available in node_modules/${PACKAGE_NAME}/README.md, AGENTS.md, and docs`)
|
|
30
|
+
console.log(`[${PACKAGE_NAME}] Start with README.md, AGENTS.md, docs/AI.md, docs/COMPONENTS.md, and docs/PROFILES.md`)
|
|
31
|
+
console.log(`[${PACKAGE_NAME}] Component profiles live in docs/profiles/components, page profiles live in docs/profiles/pages`)
|
|
31
32
|
|
|
32
33
|
if (!hasAgentsFile) {
|
|
33
34
|
console.log(`[${PACKAGE_NAME}] To scaffold AGENTS.md for this project, run:`)
|