@retailcrm/embed-ui-v1-components 0.9.21 → 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 +3 -3
- package/README.md +3 -4
- 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 +227 -50
- package/bin/postinstall.mjs +2 -1
- package/dist/host.cjs +1204 -488
- package/dist/host.css +629 -0
- package/dist/host.d.ts +100 -20
- package/dist/host.js +1205 -489
- package/dist/remote.cjs +1210 -153
- package/dist/remote.d.ts +786 -36
- package/dist/remote.js +1212 -155
- package/docs/AI.md +19 -20
- package/docs/COMPONENTS.md +58 -59
- package/docs/FORMAT.md +6 -8
- package/docs/PROFILES.md +34 -21
- package/docs/README.md +3 -6
- package/docs/profiles/{UiAddButton.yml → components/UiAddButton.yml} +49 -2
- package/docs/profiles/{UiAlert.yml → components/UiAlert.yml} +32 -2
- package/docs/profiles/{UiAvatar.yml → components/UiAvatar.yml} +17 -3
- package/docs/profiles/{UiAvatarList.yml → components/UiAvatarList.yml} +0 -2
- package/docs/profiles/{UiButton.yml → components/UiButton.yml} +14 -1
- package/docs/profiles/components/UiCalendar.yml +190 -0
- package/docs/profiles/{UiCheckbox.yml → components/UiCheckbox.yml} +28 -2
- package/docs/profiles/{UiCollapse.yml → components/UiCollapse.yml} +57 -2
- package/docs/profiles/{UiCollapseBox.yml → components/UiCollapseBox.yml} +64 -2
- package/docs/profiles/{UiCollapseGroup.yml → components/UiCollapseGroup.yml} +0 -2
- package/docs/profiles/{UiCopyButton.yml → components/UiCopyButton.yml} +19 -2
- package/docs/profiles/{UiDate.yml → components/UiDate.yml} +20 -2
- package/docs/profiles/{UiDatePicker.yml → components/UiDatePicker.yml} +51 -2
- package/docs/profiles/{UiError.yml → components/UiError.yml} +48 -2
- package/docs/profiles/{UiField.yml → components/UiField.yml} +46 -1
- package/docs/profiles/{UiInfobox.yml → components/UiInfobox.yml} +54 -2
- package/docs/profiles/{UiLink.yml → components/UiLink.yml} +22 -2
- package/docs/profiles/{UiLoader.yml → components/UiLoader.yml} +0 -2
- package/docs/profiles/{UiMenuItem.yml → components/UiMenuItem.yml} +0 -2
- package/docs/profiles/{UiMenuItemGroup.yml → components/UiMenuItemGroup.yml} +0 -2
- package/docs/profiles/{UiModalSidebar.yml → components/UiModalSidebar.yml} +80 -2
- package/docs/profiles/components/UiModalWindow.yml +181 -0
- package/docs/profiles/{UiModalWindowSurface.yml → components/UiModalWindowSurface.yml} +0 -2
- package/docs/profiles/{UiNumberStepper.yml → components/UiNumberStepper.yml} +14 -2
- package/docs/profiles/{UiPageHeader.yml → components/UiPageHeader.yml} +39 -1
- package/docs/profiles/components/UiPopconfirm.yml +164 -0
- package/docs/profiles/{UiPopper.yml → components/UiPopper.yml} +66 -1
- package/docs/profiles/{UiPopperConnector.yml → components/UiPopperConnector.yml} +0 -2
- package/docs/profiles/{UiPopperTarget.yml → components/UiPopperTarget.yml} +0 -2
- package/docs/profiles/{UiRadio.yml → components/UiRadio.yml} +15 -2
- package/docs/profiles/{UiRadioSwitch.yml → components/UiRadioSwitch.yml} +55 -1
- package/docs/profiles/{UiRadioSwitchOption.yml → components/UiRadioSwitchOption.yml} +0 -2
- package/docs/profiles/{UiScrollBox.yml → components/UiScrollBox.yml} +45 -2
- package/docs/profiles/{UiSelect.yml → components/UiSelect.yml} +133 -1
- package/docs/profiles/{UiSelectOption.yml → components/UiSelectOption.yml} +0 -2
- package/docs/profiles/{UiSelectOptionGroup.yml → components/UiSelectOptionGroup.yml} +0 -2
- package/docs/profiles/{UiSkeleton.yml → components/UiSkeleton.yml} +11 -2
- package/docs/profiles/{UiSlider.yml → components/UiSlider.yml} +85 -2
- package/docs/profiles/{UiSwitch.yml → components/UiSwitch.yml} +50 -2
- package/docs/profiles/{UiTab.yml → components/UiTab.yml} +126 -2
- package/docs/profiles/{UiTabGroup.yml → components/UiTabGroup.yml} +0 -1
- package/docs/profiles/components/UiTable.yml +622 -0
- package/docs/profiles/{UiTableBodyCell.yml → components/UiTableBodyCell.yml} +0 -2
- package/docs/profiles/{UiTableColumn.yml → components/UiTableColumn.yml} +0 -2
- package/docs/profiles/{UiTableFooterButton.yml → components/UiTableFooterButton.yml} +0 -2
- package/docs/profiles/{UiTableFooterSection.yml → components/UiTableFooterSection.yml} +0 -2
- package/docs/profiles/{UiTableHeadCell.yml → components/UiTableHeadCell.yml} +0 -2
- package/docs/profiles/{UiTableSorter.yml → components/UiTableSorter.yml} +0 -2
- package/docs/profiles/{UiTag.yml → components/UiTag.yml} +13 -2
- package/docs/profiles/{UiTextbox.yml → components/UiTextbox.yml} +20 -1
- package/docs/profiles/{UiTimePicker.yml → components/UiTimePicker.yml} +60 -2
- package/docs/profiles/{UiToggleButton.yml → components/UiToggleButton.yml} +16 -1
- package/docs/profiles/{UiToggleGroup.yml → components/UiToggleGroup.yml} +25 -1
- package/docs/profiles/{UiToggleGroupOption.yml → components/UiToggleGroupOption.yml} +0 -2
- package/docs/profiles/{UiToolbarButton.yml → components/UiToolbarButton.yml} +15 -2
- package/docs/profiles/{UiToolbarLink.yml → components/UiToolbarLink.yml} +13 -2
- package/docs/profiles/{UiTooltip.yml → components/UiTooltip.yml} +18 -2
- package/docs/profiles/{UiTransition.yml → components/UiTransition.yml} +0 -2
- package/docs/profiles/{UiYandexMap.yml → components/UiYandexMap.yml} +24 -2
- 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 +1 -1
- package/docs/AGENT-DESIGN-GUIDELINES.md +0 -463
- package/docs/assets/page-guidelines/card-settings-page.png +0 -0
- package/docs/assets/page-guidelines/collapse-block-page.png +0 -0
- package/docs/assets/page-guidelines/entity-list-page.png +0 -0
- package/docs/assets/page-guidelines/modal-sidebar.png +0 -0
- package/docs/assets/page-guidelines/modal-window.png +0 -0
- package/docs/assets/page-guidelines/multi-column-page.png +0 -0
- package/docs/profiles/UiCalendar.yml +0 -76
- package/docs/profiles/UiImage.yml +0 -67
- package/docs/profiles/UiModalWindow.yml +0 -86
- package/docs/profiles/UiTable.yml +0 -300
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
|
|
@@ -123,12 +123,12 @@ const save = () => {}
|
|
|
123
123
|
- Machine-oriented package summary:
|
|
124
124
|
[`./docs/AI.md`](./docs/AI.md)
|
|
125
125
|
- Page composition guidelines:
|
|
126
|
-
[`./docs/
|
|
126
|
+
[`./docs/profiles/pages`](./docs/profiles/pages)
|
|
127
127
|
- Component profiles:
|
|
128
128
|
[`./docs/PROFILES.md`](./docs/PROFILES.md)
|
|
129
129
|
|
|
130
130
|
For table, catalog, registry, journal, or search-result screens, read [`./docs/AI.md`](./docs/AI.md)
|
|
131
|
-
and [`./docs/
|
|
131
|
+
and [`./docs/profiles/pages/EntityListPage.yml`](./docs/profiles/pages/EntityListPage.yml), then check the
|
|
132
132
|
`UiTable` and `UiLink` profiles before generating code. Put filters above the table, persist
|
|
133
133
|
filters and pagination in GET query parameters when routing exists, and set `size="small"` on
|
|
134
134
|
`UiLink` inside table cells by default.
|
package/README.md
CHANGED
|
@@ -50,15 +50,14 @@ import { UiButton } from '@retailcrm/embed-ui-v1-components/remote'
|
|
|
50
50
|
- [`docs/README.md`](./docs/README.md) — обзор пакета и правил использования.
|
|
51
51
|
- [`docs/COMPONENTS.md`](./docs/COMPONENTS.md) — карта публичных компонентов.
|
|
52
52
|
- [`docs/AI.md`](./docs/AI.md) — контекст для ИИ и автоматизаций.
|
|
53
|
-
- [`docs/PROFILES.md`](./docs/PROFILES.md) — AI-friendly YAML-профили
|
|
53
|
+
- [`docs/PROFILES.md`](./docs/PROFILES.md) — AI-friendly YAML-профили компонентов и страниц.
|
|
54
54
|
- [`docs/FORMAT.md`](./docs/FORMAT.md) — формат описания компонента для AI-агентов.
|
|
55
|
-
- [`docs/
|
|
56
|
-
модалок, шторок, фильтров и таблиц.
|
|
55
|
+
- [`docs/profiles/pages`](./docs/profiles/pages) — YAML-профили страниц, модалок, шторок, фильтров и таблиц.
|
|
57
56
|
|
|
58
57
|
## AI и инициализация `AGENTS.md`
|
|
59
58
|
|
|
60
59
|
После установки пакет показывает подсказку, что внутри есть `README.md`, `AGENTS.md`,
|
|
61
|
-
AI-заметки и YAML-профили
|
|
60
|
+
AI-заметки и YAML-профили компонентов и страниц.
|
|
62
61
|
|
|
63
62
|
Если в целевом проекте еще нет `AGENTS.md`, можно сгенерировать стартовый файл командой:
|
|
64
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,25 +200,33 @@ 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 read
|
|
80
|
-
4. Then read
|
|
81
|
-
5. Then
|
|
82
|
-
6.
|
|
83
|
-
7.
|
|
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:
|
|
84
225
|
- \`${PACKAGE_NAME}/remote\`
|
|
85
226
|
- \`${PACKAGE_NAME}/host\`
|
|
86
227
|
- \`${PACKAGE_NAME}/assets/...\`
|
|
87
|
-
|
|
88
|
-
|
|
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.
|
|
89
230
|
|
|
90
231
|
## Suggested Reading Order
|
|
91
232
|
|
|
@@ -93,65 +234,100 @@ When working with \`${PACKAGE_NAME}\` in this project:
|
|
|
93
234
|
2. \`AGENTS.md\`
|
|
94
235
|
3. \`docs/AI.md\`
|
|
95
236
|
4. \`docs/COMPONENTS.md\`
|
|
96
|
-
5.
|
|
97
|
-
6.
|
|
98
|
-
7.
|
|
99
|
-
|
|
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
|
+
`
|
|
100
244
|
}
|
|
101
245
|
|
|
102
|
-
const
|
|
103
|
-
|
|
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)
|
|
104
249
|
|
|
105
|
-
|
|
250
|
+
if (start === -1 && end === -1) {
|
|
251
|
+
return null
|
|
252
|
+
}
|
|
106
253
|
|
|
107
|
-
1
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
4. Then read \`./node_modules/${PACKAGE_NAME}/docs/COMPONENTS.md\`.
|
|
111
|
-
5. Then open the relevant profile from \`./node_modules/${PACKAGE_NAME}/docs/profiles/<Component>.yml\`.
|
|
112
|
-
6. Prefer those docs and profiles over guessing from internal implementation files.
|
|
113
|
-
7. Import only from documented public entrypoints:
|
|
114
|
-
- \`${PACKAGE_NAME}/remote\`
|
|
115
|
-
- \`${PACKAGE_NAME}/host\`
|
|
116
|
-
- \`${PACKAGE_NAME}/assets/...\`
|
|
117
|
-
8. Prefer \`${PACKAGE_NAME}/remote\` for extension UI code.
|
|
118
|
-
9. 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
|
+
}
|
|
119
257
|
|
|
120
|
-
|
|
258
|
+
return {
|
|
259
|
+
start,
|
|
260
|
+
end: end + AGENTS_SECTION_END.length,
|
|
261
|
+
}
|
|
262
|
+
}
|
|
121
263
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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
|
+
}
|
|
130
283
|
}
|
|
131
284
|
|
|
132
|
-
const hasPackageSection = (content) =>
|
|
285
|
+
const hasPackageSection = (content) => {
|
|
286
|
+
return Boolean(findMarkedSectionRange(content) || findLegacySectionRange(content))
|
|
287
|
+
}
|
|
133
288
|
|
|
134
289
|
const appendSection = (content, section) => {
|
|
135
290
|
const trimmed = content.replace(/\s+$/u, '')
|
|
136
291
|
|
|
137
292
|
if (!trimmed.length) {
|
|
138
|
-
return `${section}${DEFAULT_NEWLINE}`
|
|
293
|
+
return `${section.trimEnd()}${DEFAULT_NEWLINE}`
|
|
139
294
|
}
|
|
140
295
|
|
|
141
|
-
return `${trimmed}${DEFAULT_NEWLINE}${DEFAULT_NEWLINE}${section}${DEFAULT_NEWLINE}`
|
|
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)
|
|
306
|
+
}
|
|
307
|
+
|
|
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}`
|
|
142
315
|
}
|
|
143
316
|
|
|
144
317
|
const replaceSection = (content, section) => {
|
|
145
|
-
const
|
|
146
|
-
|
|
318
|
+
const markedRange = findMarkedSectionRange(content)
|
|
319
|
+
|
|
320
|
+
if (markedRange) {
|
|
321
|
+
return replaceRange(content, markedRange, section)
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const legacyRange = findLegacySectionRange(content)
|
|
147
325
|
|
|
148
|
-
if (
|
|
149
|
-
return
|
|
326
|
+
if (legacyRange) {
|
|
327
|
+
return replaceRange(content, legacyRange, section)
|
|
150
328
|
}
|
|
151
329
|
|
|
152
|
-
return content
|
|
153
|
-
.replace(sectionPattern, section.trimEnd())
|
|
154
|
-
.replace(/\s+$/u, '') + DEFAULT_NEWLINE
|
|
330
|
+
return appendSection(content, section)
|
|
155
331
|
}
|
|
156
332
|
|
|
157
333
|
const initAgents = (target, force) => {
|
|
@@ -166,10 +342,11 @@ const initAgents = (target, force) => {
|
|
|
166
342
|
}
|
|
167
343
|
|
|
168
344
|
const agentsPath = path.join(target, 'AGENTS.md')
|
|
169
|
-
const
|
|
345
|
+
const packageDocsPath = createPackageDocsPath(target)
|
|
346
|
+
const section = createAgentsSection(packageDocsPath)
|
|
170
347
|
|
|
171
348
|
if (!fs.existsSync(agentsPath)) {
|
|
172
|
-
fs.writeFileSync(agentsPath, createAgentsTemplate(), 'utf8')
|
|
349
|
+
fs.writeFileSync(agentsPath, createAgentsTemplate(packageDocsPath), 'utf8')
|
|
173
350
|
|
|
174
351
|
console.log(`AGENTS.md was created at ${agentsPath}`)
|
|
175
352
|
console.log('Next step: review it and adjust project-specific rules if needed.')
|
package/bin/postinstall.mjs
CHANGED
|
@@ -27,7 +27,8 @@ const hasAgentsFile = fs.existsSync(agentsPath)
|
|
|
27
27
|
|
|
28
28
|
console.log('')
|
|
29
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/
|
|
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:`)
|