Skip to content

Commit 603ecef

Browse files
docs: update dev docs about esm, building and testing
1 parent c71995a commit 603ecef

File tree

5 files changed

+77
-45
lines changed

5 files changed

+77
-45
lines changed

turbo.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"envMode": "loose",
66
"tasks": {
77
"build:bin": {
8-
"outputs": ["dist/scripts/**"]
8+
"outputs": ["dist/bin/**"]
99
},
1010
"build:xmlui": {
1111
"outputs": ["dist/lib/**"]

xmlui/conventions/testing-conventions.md

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ There's also documentation in the `.md` files, next to the component's file.
7070
**ALWAYS read the component's `.tsx` file before creating tests.** The component files contain essential metadata that documents:
7171

7272
- **Properties**: All available props with their types and descriptions
73-
- **Events**: Available event handlers and their parameters
73+
- **Events**: Available event handlers and their parameters
7474
- **Theme Variables**: Default values and names for CSS custom properties used in theme testing
7575

7676
Use the documented theme variable names when creating theme tests instead of guessing:
@@ -95,7 +95,8 @@ test("applies theme variables", async ({ initTestBed, page }) => {
9595
- **Provides context** for proper testing scenarios
9696

9797
Example documentation locations:
98-
- `Button.tsx` - Contains metadata
98+
99+
- `Button.tsx` - Contains metadata
99100
- `Button.md` - Contains examples and detailed usage
100101
- `Button.spec.ts` - Your test file
101102

@@ -400,10 +401,10 @@ test("enqueueItem returns valid ID", async ({ initTestBed, createButtonDriver })
400401
<Button onClick="testState = { id: testQueue.enqueueItem('test'), hasId: true }" />
401402
</Fragment>
402403
`);
403-
404+
404405
const buttonDriver = await createButtonDriver("button");
405406
await buttonDriver.component.click();
406-
407+
407408
const result = await testStateDriver.testState();
408409
expect(result.id).toBeTruthy();
409410
expect(result.hasId).toBe(true);
@@ -489,6 +490,14 @@ Use web-first assertions, like `await expect(checkboxLocator).not.toBeChecked()`
489490

490491
## Best Practices
491492

493+
### Avoid Frontend Code in E2E Tests
494+
495+
It is crucial to avoid importing frontend code into E2E tests, especially if it transitively imports stylesheets. This can lead to unexpected issues with the test runner and slow down test execution.
496+
497+
For example, importing `defaultProps` from a component file like `ButtonNative.tsx` into a test file like `Button.spec.ts` is an anti-pattern. The component file likely imports SCSS or CSS files, which should not be part of the test environment.
498+
499+
Instead, if you need to share data between your component and your tests, define it in a separate file that can be imported safely by both.
500+
492501
### Skipping tests
493502

494503
#### Skipping For coverage
@@ -545,7 +554,7 @@ Components that support layout properties (like `labelPosition`, `direction`, po
545554

546555
#### Best Practices for Layout Testing
547556

548-
- **Import getBounds**: Import from `"../../testing/component-test-helpers"`
557+
- **Import getBounds**: Import from `"../../testing/component-test-helpers"`
549558
- **Use descriptive coordinates**: Destructure specific properties like `{ left, right, top, bottom }`
550559
- **Test both directions**: Include RTL tests when direction affects layout
551560
- **Verify invalid values**: Test graceful handling of invalid layout properties
@@ -555,7 +564,10 @@ Components that support layout properties (like `labelPosition`, `direction`, po
555564
Use `getBounds()` to get element coordinates and verify relative positioning:
556565

557566
```typescript
558-
test("ComponentName appears at the correct side of ComponentName2", async ({ initTestBed, page }) => {
567+
test("ComponentName appears at the correct side of ComponentName2", async ({
568+
initTestBed,
569+
page,
570+
}) => {
559571
await initTestBed(`
560572
<Fragment>
561573
<ComponentName testId="comp1" />
@@ -614,9 +626,7 @@ test("all adornments appear in the right place", async ({ initTestBed, page }) =
614626
const { left: startIconLeft, right: startIconRight } = await getBounds(
615627
page.getByRole("img").first(),
616628
);
617-
const { left: endIconLeft, right: endIconRight } = await getBounds(
618-
page.getByRole("img").last(),
619-
);
629+
const { left: endIconLeft, right: endIconRight } = await getBounds(page.getByRole("img").last());
620630

621631
// Check order of adornments relative to their container component bounds
622632
expect(startTextRight - compLeft).toBeLessThanOrEqual(compRight - startTextLeft);

xmlui/dev-docs/build-system.md

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -428,25 +428,24 @@ src/
428428
```
429429
dist/
430430
├── lib/ # Library build
431-
│ ├── xmlui.mjs
431+
│ ├── xmlui.js
432432
│ ├── xmlui.d.ts
433-
│ ├── xmlui-parser.mjs
434-
│ ├── language-server.mjs
433+
│ ├── xmlui-parser.js
434+
│ ├── language-server.js
435435
│ └── scss/ # SCSS source files
436436
├── standalone/ # Standalone build
437437
│ └── xmlui-standalone.umd.js
438438
├── metadata/ # Metadata build
439439
│ └── xmlui-metadata.js
440-
└── scripts/
441-
└── bin/
442-
└── vite-xmlui-plugin.js
440+
└── bin/
441+
└── index.js
443442
```
444443

445444
### Bin Scripts
446445

447446
```
448447
bin/
449-
├── bootstrap.js # CLI entry (ts-node setup)
448+
├── bootstrap.js # CLI entry for development (uses tsx)
450449
├── index.ts # Command router
451450
├── build.ts # Build implementation
452451
├── build-lib.ts # Library build
@@ -726,7 +725,7 @@ This table summarizes when to run builds across different contexts:
726725
| **xmlui/** | Building standalone | `npm run build:xmlui-standalone` | `vite build --mode standalone` | For CDN/buildless | Creates self-contained UMD bundle for `<script>` tag usage; framework builds itself with Vite directly |
727726
| **xmlui/** | Generating metadata | `npm run build:xmlui-metadata` | `vite build --mode metadata` | After component changes, before doc generation | Extracts component metadata into `xmlui-metadata.js` for documentation generation and language server autocomplete. This is the source of truth for component APIs, props, and descriptions. Framework uses Vite directly. |
728727
| **xmlui/** | Full doc generation | `npm run generate-all-docs` | Node scripts (not CLI) | After metadata changes | Runs three scripts: (1) `build:xmlui-metadata` - extracts metadata, (2) `generate-docs` - creates component .md files from metadata, (3) `generate-docs-summaries` - creates overview/summary files. This is the complete pipeline from source code → documentation |
729-
| **xmlui/** | Compile bin scripts | `npm run build:bin` | `tsc -p tsconfig.bin.json` | After changes to bin/\*.ts files | Compiles TypeScript bin scripts (CLI tools) to JavaScript using TypeScript directly; needed when modifying build system or CLI commands |
728+
| **xmlui/** | Compile bin scripts | `npm run build:bin` | `tsdown` | After changes to bin/\*.ts files | Compiles TypeScript bin scripts (CLI tools) to JavaScript using tsdown (see tsdown.config.ts); needed when modifying build system or CLI commands |
730729
| **extension/** | Development | `npm start` | `xmlui start` | Keep running during dev | Runs dev server with HMR for demo app; use with build-watch in separate terminal |
731730
| **extension/** | Watch mode build | `npm run build-watch` | `xmlui build-lib --watch` | Keep running during dev | Continuously rebuilds extension library on changes; pair with `npm start` for rapid iteration |
732731
| **extension/** | Building for publish | `npm run build:extension` | `xmlui build-lib` | Before npm publish | Creates distributable library bundle (.mjs, .js, .d.ts, CSS) for npm package |

xmlui/dev-docs/build-xmlui.md

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ The XMLUI framework package is built using **Vite** with multiple build modes. T
3535
npm run build-xmlui # Build entire XMLUI core package
3636

3737
# From xmlui/ directory
38-
npm run build:bin # Build CLI tools
38+
npm run build:bin # Build CLI tools using tsdown
3939
npm run build:xmlui # Build library mode
4040
npm run build:xmlui-standalone # Build UMD bundle
4141
npm run build:xmlui-metadata # Extract component metadata
@@ -47,7 +47,7 @@ npm run build:xmlui-metadata # Extract component metadata
4747

4848
| Mode | Entry Point | Output Format | Purpose |
4949
| -------------- | ----------------------------- | -------------------- | ------------------------ |
50-
| **lib** | Multiple entries | ES Modules (.mjs) | npm package distribution |
50+
| **lib** | Multiple entries | ES Modules (.js) | npm package distribution |
5151
| **standalone** | index-standalone.ts | UMD bundle (.umd.js) | Buildless CDN deployment |
5252
| **metadata** | collectedComponentMetadata.ts | ES Module | Documentation/LSP |
5353

@@ -136,13 +136,13 @@ copy({
136136

137137
```
138138
dist/lib/
139-
├── xmlui.mjs # Main framework bundle
139+
├── xmlui.js # Main framework bundle
140140
├── xmlui.d.ts # Bundled type definitions
141-
├── xmlui-parser.mjs # Parser bundle
142-
├── language-server.mjs # LSP server bundle
143-
├── language-server-web-worker.mjs # Browser LSP bundle
144-
├── syntax-monaco.mjs # Monaco syntax bundle
145-
├── syntax-textmate.mjs # TextMate syntax bundle
141+
├── xmlui-parser.js # Parser bundle
142+
├── language-server.js # LSP server bundle
143+
├── language-server-web-worker.js # Browser LSP bundle
144+
├── syntax-monaco.js # Monaco syntax bundle
145+
├── syntax-textmate.js # TextMate syntax bundle
146146
├── *.css # Extracted component styles
147147
└── scss/ # Source SCSS files
148148
└── (mirrors src/ structure)
@@ -154,35 +154,53 @@ After `clean-package` transforms package.json during publish:
154154

155155
```json
156156
{
157-
"main": "./dist/lib/xmlui.js",
157+
"main": "./dist/standalone/xmlui-standalone.umd.js",
158+
"module": "./dist/lib/xmlui.js",
158159
"types": "./dist/lib/xmlui.d.ts",
159160
"exports": {
160161
".": {
161-
"import": "./dist/lib/xmlui.js"
162-
},
163-
"./parser": {
164-
"import": "./dist/lib/xmlui-parser.js"
162+
"import": "./dist/lib/xmlui.js",
163+
"require": "./dist/standalone/xmlui-standalone.umd.js"
165164
},
166165
"./language-server": {
167-
"import": "./dist/lib/language-server.js"
166+
"import": "./dist/lib/language-server.js",
167+
"require": "./dist/lib/language-server.js"
168168
},
169169
"./language-server-web-worker": {
170-
"import": "./dist/lib/language-server-web-worker.js"
170+
"import": "./dist/lib/language-server-web-worker.js",
171+
"require": "./dist/lib/language-server-web-worker.js"
171172
},
172-
"./syntax/monaco": {
173-
"import": "./dist/lib/syntax-monaco.js"
174-
},
175-
"./syntax/textmate": {
176-
"import": "./dist/lib/syntax-textmate.js"
173+
"./parser": {
174+
"import": "./dist/lib/xmlui-parser.js",
175+
"require": "./dist/lib/xmlui-parser.js"
177176
},
178177
"./*.css": {
179-
"import": "./dist/lib/*.css"
178+
"import": "./dist/lib/*.css",
179+
"require": "./dist/lib/*.css"
180180
},
181181
"./index.scss": {
182-
"import": "./dist/lib/scss/index.scss"
182+
"import": "./dist/lib/scss/index.scss",
183+
"require": "./dist/lib/scss/index.scss"
184+
},
185+
"./themes.scss": {
186+
"import": "./dist/lib/scss/components-core/theming/_themes.scss",
187+
"require": "./dist/lib/scss/components-core/theming/_themes.scss"
183188
},
184189
"./vite-xmlui-plugin": {
185-
"import": "./dist/scripts/bin/vite-xmlui-plugin.js"
190+
"import": "./dist/lib/vite-xmlui-plugin/index.js",
191+
"require": "./dist/lib/vite-xmlui-plugin/index.js"
192+
},
193+
"./syntax/monaco": {
194+
"import": "./dist/lib/syntax-monaco.js",
195+
"require": "./dist/lib/syntax-monaco.js"
196+
},
197+
"./syntax/textmate": {
198+
"import": "./dist/lib/syntax-textmate.js",
199+
"require": "./dist/lib/syntax-textmate.js"
200+
},
201+
"./testing": {
202+
"import": "./dist/lib/testing.js",
203+
"require": "./dist/lib/testing.js"
186204
}
187205
}
188206
}
@@ -360,8 +378,8 @@ This internally runs in order:
360378
```bash
361379
# 1. Build CLI tools
362380
npm run build:bin
363-
# Compiles TypeScript in bin/ folder using tsconfig.bin.json
364-
# Output: bin/*.js files
381+
# Compiles TypeScript in bin/ folder using tsdown (see tsdown.config.ts)
382+
# Output: dist/bin/
365383

366384
# 2. Build library for npm
367385
npm run build:xmlui
@@ -405,11 +423,16 @@ The `clean-package` tool transforms package.json during publish:
405423
{
406424
"main": "./dist/lib/xmlui.js",
407425
"bin": {
408-
"xmlui": "dist/scripts/bin/bootstrap.js"
426+
"xmlui": "dist/bin/index.js"
409427
}
410428
}
411429
```
412430

431+
> **Note on CLI Development:**
432+
> In the development environment, the `xmlui` command points to `bin/bootstrap.js`. This file uses `tsx` to execute the CLI's TypeScript source (`bin/index.ts`) on-the-fly. This allows for rapid development of the CLI without requiring a separate build step for every change.
433+
>
434+
> For production, `clean-package` replaces the `bin` entry to point to the compiled `dist/bin/index.js`, ensuring the published package does not rely on `tsx`.
435+
413436
## Vite Configuration
414437

415438
### Target and Optimization

xmlui/dev-docs/xmlui-repo.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ The `turbo.json` file at the repository root defines all tasks and their orchest
187187

188188
```json
189189
{
190-
"outputs": ["dist/scripts/**"]
190+
"outputs": ["dist/bin/**"]
191191
}
192192
```
193193

0 commit comments

Comments
 (0)