semmet-angular 0.28.0 → 0.29.0
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/README.en.md +11 -0
- package/README.md +11 -0
- package/README.pt-BR.md +11 -0
- package/package.json +1 -1
- package/src/ci/index.d.ts +3 -0
- package/src/ci/index.js +117 -0
- package/src/ci/index.js.map +1 -0
- package/src/ci/index.ts +143 -0
- package/src/ci/schema.d.ts +4 -0
- package/src/ci/schema.js +3 -0
- package/src/ci/schema.js.map +1 -0
- package/src/ci/schema.json +20 -0
- package/src/ci/schema.ts +4 -0
- package/src/collection.json +5 -0
package/README.en.md
CHANGED
|
@@ -19,6 +19,7 @@ Brazilian Portuguese documentation is available in [README.md](./README.md).
|
|
|
19
19
|
```
|
|
20
20
|
ng add semmet-angular
|
|
21
21
|
ng generate semmet-angular:accordion my-faq
|
|
22
|
+
ng generate semmet-angular:ci
|
|
22
23
|
```
|
|
23
24
|
|
|
24
25
|
`ng add semmet-angular` installs the package and configures the delivery workflow once for the target application, including Playwright e2e support and npm scripts. Each generated component is dropped into your project exactly like `ng generate component` would (respecting your `angular.json` project, source root, and selector prefix), and has **zero runtime dependency** on this package — `semmet-angular` is only needed at generation time.
|
|
@@ -47,6 +48,16 @@ npm run e2e:ui
|
|
|
47
48
|
|
|
48
49
|
`npm run e2e` runs Playwright against the Angular dev server configured by `playwright.config.ts`; `npm run e2e:ui` opens Playwright's interactive UI.
|
|
49
50
|
|
|
51
|
+
## GitHub Actions CI
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
ng generate semmet-angular:ci
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
This command generates `.github/workflows/ci.yml` using the package scripts that already exist in `package.json`. The workflow detects the package manager by lockfile (`package-lock.json`, `pnpm-lock.yaml`, or `yarn.lock`), installs dependencies, and runs `verify` when available. If `verify` does not exist yet, it runs `build`, `test`, and `e2e` when those scripts exist.
|
|
58
|
+
|
|
59
|
+
By default, the schematic does not overwrite an existing workflow. Use `--force` when you want to replace `.github/workflows/ci.yml`.
|
|
60
|
+
|
|
50
61
|
## Projected content containers
|
|
51
62
|
|
|
52
63
|
Some generated components are containers: they own the ARIA wiring, keyboard behavior, focus management, and visual shell, while your app owns the content rendered inside them.
|
package/README.md
CHANGED
|
@@ -19,6 +19,7 @@ English documentation is available in [README.en.md](./README.en.md).
|
|
|
19
19
|
```bash
|
|
20
20
|
ng add semmet-angular
|
|
21
21
|
ng generate semmet-angular:accordion minha-faq
|
|
22
|
+
ng generate semmet-angular:ci
|
|
22
23
|
```
|
|
23
24
|
|
|
24
25
|
`ng add semmet-angular` instala o pacote e configura uma vez o fluxo de entrega da aplicação alvo, incluindo suporte a e2e com Playwright e scripts npm. Cada componente gerado entra no seu projeto do mesmo jeito que entraria com `ng generate component` (respeitando `angular.json`, `sourceRoot` e prefixo de seletor), e tem **zero dependência em tempo de execução** deste pacote — `semmet-angular` só é necessário na geração.
|
|
@@ -47,6 +48,16 @@ npm run lint
|
|
|
47
48
|
|
|
48
49
|
`lint` só entra quando a aplicação já tem um script `lint`; `build` e `test` seguem a mesma lógica. O `e2e` entra depois da configuração do Playwright feita pelo `ng add`.
|
|
49
50
|
|
|
51
|
+
## CI com GitHub Actions
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
ng generate semmet-angular:ci
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Esse comando gera `.github/workflows/ci.yml` usando os scripts já existentes no `package.json`. O workflow detecta o gerenciador de pacotes por lockfile (`package-lock.json`, `pnpm-lock.yaml` ou `yarn.lock`), instala dependências e executa `verify` quando disponível. Se `verify` ainda não existir, ele roda `build`, `test` e `e2e` conforme esses scripts existirem.
|
|
58
|
+
|
|
59
|
+
Por padrão, o schematic não sobrescreve um workflow existente. Use `--force` quando quiser substituir `.github/workflows/ci.yml`.
|
|
60
|
+
|
|
50
61
|
## Testes Gerados
|
|
51
62
|
|
|
52
63
|
Todo schematic de componente gera arquivos de teste ao lado do componente:
|
package/README.pt-BR.md
CHANGED
|
@@ -17,6 +17,7 @@ Leia a direção geral do produto em [PRODUCT_VISION.md](./PRODUCT_VISION.md).
|
|
|
17
17
|
```bash
|
|
18
18
|
ng add semmet-angular
|
|
19
19
|
ng generate semmet-angular:accordion minha-faq
|
|
20
|
+
ng generate semmet-angular:ci
|
|
20
21
|
```
|
|
21
22
|
|
|
22
23
|
`ng add semmet-angular` instala o pacote e configura uma vez o fluxo de entrega da aplicação alvo, incluindo suporte a e2e com Playwright e scripts npm. Cada componente gerado entra no seu projeto do mesmo jeito que entraria com `ng generate component` (respeitando `angular.json`, `sourceRoot` e prefixo de seletor), e tem **zero dependência em tempo de execução** deste pacote — `semmet-angular` só é necessário na geração.
|
|
@@ -45,6 +46,16 @@ npm run lint
|
|
|
45
46
|
|
|
46
47
|
`lint` só entra quando a aplicação já tem um script `lint`; `build` e `test` seguem a mesma lógica. O `e2e` entra depois da configuração do Playwright feita pelo `ng add`.
|
|
47
48
|
|
|
49
|
+
## CI com GitHub Actions
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
ng generate semmet-angular:ci
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Esse comando gera `.github/workflows/ci.yml` usando os scripts já existentes no `package.json`. O workflow detecta o gerenciador de pacotes por lockfile (`package-lock.json`, `pnpm-lock.yaml` ou `yarn.lock`), instala dependências e executa `verify` quando disponível. Se `verify` ainda não existir, ele roda `build`, `test` e `e2e` conforme esses scripts existirem.
|
|
56
|
+
|
|
57
|
+
Por padrão, o schematic não sobrescreve um workflow existente. Use `--force` quando quiser substituir `.github/workflows/ci.yml`.
|
|
58
|
+
|
|
48
59
|
## Testes Gerados
|
|
49
60
|
|
|
50
61
|
Todo schematic de componente gera arquivos de teste ao lado do componente:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "semmet-angular",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0",
|
|
4
4
|
"description": "Accessible UI Delivery Kit for Angular: schematics that generate ARIA-conformant standalone components with styling, keyboard behavior, unit tests, and Playwright e2e smoke tests.",
|
|
5
5
|
"publisher": "danilodevsilva",
|
|
6
6
|
"license": "MIT",
|
package/src/ci/index.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ci = ci;
|
|
4
|
+
const schematics_1 = require("@angular-devkit/schematics");
|
|
5
|
+
function ci(options) {
|
|
6
|
+
return (tree) => {
|
|
7
|
+
const workflowPath = buildWorkflowPath(options.name);
|
|
8
|
+
if (tree.exists(workflowPath) && !options.force) {
|
|
9
|
+
throw new schematics_1.SchematicsException(`${workflowPath} already exists. Re-run with --force to overwrite it.`);
|
|
10
|
+
}
|
|
11
|
+
const packageJson = readJson(tree, '/package.json');
|
|
12
|
+
const scripts = packageJson.scripts ?? {};
|
|
13
|
+
const packageManager = detectPackageManager(tree);
|
|
14
|
+
const workflow = buildWorkflow(packageManager, Object.keys(scripts), tree.exists('/package-lock.json'));
|
|
15
|
+
if (tree.exists(workflowPath)) {
|
|
16
|
+
tree.overwrite(workflowPath, workflow);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
tree.create(workflowPath, workflow);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function buildWorkflowPath(name = 'ci') {
|
|
24
|
+
const normalizedName = name.trim().replace(/\.ya?ml$/, '');
|
|
25
|
+
if (!normalizedName || normalizedName.includes('/') || normalizedName.includes('\\')) {
|
|
26
|
+
throw new schematics_1.SchematicsException('CI workflow name must be a file name without path separators.');
|
|
27
|
+
}
|
|
28
|
+
return `/.github/workflows/${normalizedName}.yml`;
|
|
29
|
+
}
|
|
30
|
+
function detectPackageManager(tree) {
|
|
31
|
+
if (tree.exists('/pnpm-lock.yaml')) {
|
|
32
|
+
return 'pnpm';
|
|
33
|
+
}
|
|
34
|
+
if (tree.exists('/yarn.lock')) {
|
|
35
|
+
return 'yarn';
|
|
36
|
+
}
|
|
37
|
+
return 'npm';
|
|
38
|
+
}
|
|
39
|
+
function buildWorkflow(packageManager, scriptNames, hasNpmLockfile) {
|
|
40
|
+
const commands = getPackageManagerCommands(packageManager, hasNpmLockfile);
|
|
41
|
+
const runSteps = buildRunSteps(commands, scriptNames);
|
|
42
|
+
const setupPackageManagerStep = commands.setupStep ? `${commands.setupStep}\n` : '';
|
|
43
|
+
const cacheConfig = commands.cache ? ` cache: ${commands.cache}\n` : '';
|
|
44
|
+
return `name: CI
|
|
45
|
+
|
|
46
|
+
on:
|
|
47
|
+
push:
|
|
48
|
+
branches: [main]
|
|
49
|
+
pull_request:
|
|
50
|
+
|
|
51
|
+
jobs:
|
|
52
|
+
verify:
|
|
53
|
+
runs-on: ubuntu-latest
|
|
54
|
+
|
|
55
|
+
steps:
|
|
56
|
+
- name: Checkout
|
|
57
|
+
uses: actions/checkout@v4
|
|
58
|
+
|
|
59
|
+
${setupPackageManagerStep} - name: Setup Node
|
|
60
|
+
uses: actions/setup-node@v4
|
|
61
|
+
with:
|
|
62
|
+
node-version: 20
|
|
63
|
+
${cacheConfig}
|
|
64
|
+
|
|
65
|
+
- name: Install dependencies
|
|
66
|
+
run: ${commands.install}
|
|
67
|
+
${runSteps}
|
|
68
|
+
`;
|
|
69
|
+
}
|
|
70
|
+
function getPackageManagerCommands(packageManager, hasNpmLockfile) {
|
|
71
|
+
if (packageManager === 'pnpm') {
|
|
72
|
+
return {
|
|
73
|
+
install: 'pnpm install --frozen-lockfile',
|
|
74
|
+
run: (script) => `pnpm run ${script}`,
|
|
75
|
+
setupStep: ` - name: Setup pnpm
|
|
76
|
+
uses: pnpm/action-setup@v4
|
|
77
|
+
with:
|
|
78
|
+
version: 9`,
|
|
79
|
+
cache: 'pnpm',
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if (packageManager === 'yarn') {
|
|
83
|
+
return {
|
|
84
|
+
install: 'yarn install --frozen-lockfile',
|
|
85
|
+
run: (script) => `yarn ${script}`,
|
|
86
|
+
cache: 'yarn',
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
install: hasNpmLockfile ? 'npm ci' : 'npm install',
|
|
91
|
+
run: (script) => `npm run ${script}`,
|
|
92
|
+
cache: hasNpmLockfile ? 'npm' : undefined,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function buildRunSteps(commands, scriptNames) {
|
|
96
|
+
const scripts = new Set(scriptNames);
|
|
97
|
+
const verificationScripts = scripts.has('verify')
|
|
98
|
+
? ['verify']
|
|
99
|
+
: ['build', 'test', 'e2e'].filter((script) => scripts.has(script));
|
|
100
|
+
if (verificationScripts.length === 0) {
|
|
101
|
+
return `
|
|
102
|
+
- name: Check package scripts
|
|
103
|
+
run: echo "No verify, build, test, or e2e script found in package.json."
|
|
104
|
+
`;
|
|
105
|
+
}
|
|
106
|
+
return verificationScripts
|
|
107
|
+
.map((script) => `
|
|
108
|
+
- name: Run ${script}
|
|
109
|
+
run: ${commands.run(script)}
|
|
110
|
+
`)
|
|
111
|
+
.join('');
|
|
112
|
+
}
|
|
113
|
+
function readJson(tree, path) {
|
|
114
|
+
const content = tree.readText(path);
|
|
115
|
+
return JSON.parse(content);
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"}
|
package/src/ci/index.ts
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { Rule, SchematicsException, Tree } from '@angular-devkit/schematics';
|
|
2
|
+
import { Schema } from './schema';
|
|
3
|
+
|
|
4
|
+
type PackageManager = 'npm' | 'pnpm' | 'yarn';
|
|
5
|
+
|
|
6
|
+
interface PackageManagerCommands {
|
|
7
|
+
install: string;
|
|
8
|
+
run: (script: string) => string;
|
|
9
|
+
setupStep?: string;
|
|
10
|
+
cache?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function ci(options: Schema): Rule {
|
|
14
|
+
return (tree: Tree) => {
|
|
15
|
+
const workflowPath = buildWorkflowPath(options.name);
|
|
16
|
+
|
|
17
|
+
if (tree.exists(workflowPath) && !options.force) {
|
|
18
|
+
throw new SchematicsException(`${workflowPath} already exists. Re-run with --force to overwrite it.`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const packageJson = readJson(tree, '/package.json');
|
|
22
|
+
const scripts = packageJson.scripts ?? {};
|
|
23
|
+
const packageManager = detectPackageManager(tree);
|
|
24
|
+
const workflow = buildWorkflow(packageManager, Object.keys(scripts), tree.exists('/package-lock.json'));
|
|
25
|
+
|
|
26
|
+
if (tree.exists(workflowPath)) {
|
|
27
|
+
tree.overwrite(workflowPath, workflow);
|
|
28
|
+
} else {
|
|
29
|
+
tree.create(workflowPath, workflow);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function buildWorkflowPath(name = 'ci'): string {
|
|
35
|
+
const normalizedName = name.trim().replace(/\.ya?ml$/, '');
|
|
36
|
+
|
|
37
|
+
if (!normalizedName || normalizedName.includes('/') || normalizedName.includes('\\')) {
|
|
38
|
+
throw new SchematicsException('CI workflow name must be a file name without path separators.');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return `/.github/workflows/${normalizedName}.yml`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function detectPackageManager(tree: Tree): PackageManager {
|
|
45
|
+
if (tree.exists('/pnpm-lock.yaml')) {
|
|
46
|
+
return 'pnpm';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (tree.exists('/yarn.lock')) {
|
|
50
|
+
return 'yarn';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return 'npm';
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function buildWorkflow(packageManager: PackageManager, scriptNames: string[], hasNpmLockfile: boolean): string {
|
|
57
|
+
const commands = getPackageManagerCommands(packageManager, hasNpmLockfile);
|
|
58
|
+
const runSteps = buildRunSteps(commands, scriptNames);
|
|
59
|
+
const setupPackageManagerStep = commands.setupStep ? `${commands.setupStep}\n` : '';
|
|
60
|
+
const cacheConfig = commands.cache ? ` cache: ${commands.cache}\n` : '';
|
|
61
|
+
|
|
62
|
+
return `name: CI
|
|
63
|
+
|
|
64
|
+
on:
|
|
65
|
+
push:
|
|
66
|
+
branches: [main]
|
|
67
|
+
pull_request:
|
|
68
|
+
|
|
69
|
+
jobs:
|
|
70
|
+
verify:
|
|
71
|
+
runs-on: ubuntu-latest
|
|
72
|
+
|
|
73
|
+
steps:
|
|
74
|
+
- name: Checkout
|
|
75
|
+
uses: actions/checkout@v4
|
|
76
|
+
|
|
77
|
+
${setupPackageManagerStep} - name: Setup Node
|
|
78
|
+
uses: actions/setup-node@v4
|
|
79
|
+
with:
|
|
80
|
+
node-version: 20
|
|
81
|
+
${cacheConfig}
|
|
82
|
+
|
|
83
|
+
- name: Install dependencies
|
|
84
|
+
run: ${commands.install}
|
|
85
|
+
${runSteps}
|
|
86
|
+
`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function getPackageManagerCommands(packageManager: PackageManager, hasNpmLockfile: boolean): PackageManagerCommands {
|
|
90
|
+
if (packageManager === 'pnpm') {
|
|
91
|
+
return {
|
|
92
|
+
install: 'pnpm install --frozen-lockfile',
|
|
93
|
+
run: (script) => `pnpm run ${script}`,
|
|
94
|
+
setupStep: ` - name: Setup pnpm
|
|
95
|
+
uses: pnpm/action-setup@v4
|
|
96
|
+
with:
|
|
97
|
+
version: 9`,
|
|
98
|
+
cache: 'pnpm',
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (packageManager === 'yarn') {
|
|
103
|
+
return {
|
|
104
|
+
install: 'yarn install --frozen-lockfile',
|
|
105
|
+
run: (script) => `yarn ${script}`,
|
|
106
|
+
cache: 'yarn',
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
install: hasNpmLockfile ? 'npm ci' : 'npm install',
|
|
112
|
+
run: (script) => `npm run ${script}`,
|
|
113
|
+
cache: hasNpmLockfile ? 'npm' : undefined,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function buildRunSteps(commands: PackageManagerCommands, scriptNames: string[]): string {
|
|
118
|
+
const scripts = new Set(scriptNames);
|
|
119
|
+
const verificationScripts = scripts.has('verify')
|
|
120
|
+
? ['verify']
|
|
121
|
+
: ['build', 'test', 'e2e'].filter((script) => scripts.has(script));
|
|
122
|
+
|
|
123
|
+
if (verificationScripts.length === 0) {
|
|
124
|
+
return `
|
|
125
|
+
- name: Check package scripts
|
|
126
|
+
run: echo "No verify, build, test, or e2e script found in package.json."
|
|
127
|
+
`;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return verificationScripts
|
|
131
|
+
.map(
|
|
132
|
+
(script) => `
|
|
133
|
+
- name: Run ${script}
|
|
134
|
+
run: ${commands.run(script)}
|
|
135
|
+
`
|
|
136
|
+
)
|
|
137
|
+
.join('');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function readJson(tree: Tree, path: string): Record<string, any> {
|
|
141
|
+
const content = tree.readText(path);
|
|
142
|
+
return JSON.parse(content) as Record<string, any>;
|
|
143
|
+
}
|
package/src/ci/schema.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["schema.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema",
|
|
3
|
+
"$id": "SemmetAngularCi",
|
|
4
|
+
"title": "Semmet Angular CI Options Schema",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"description": "Generates a GitHub Actions CI workflow using the target workspace package scripts.",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"properties": {
|
|
9
|
+
"force": {
|
|
10
|
+
"type": "boolean",
|
|
11
|
+
"default": false,
|
|
12
|
+
"description": "Overwrite an existing CI workflow."
|
|
13
|
+
},
|
|
14
|
+
"name": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"default": "ci",
|
|
17
|
+
"description": "The workflow file name to create under .github/workflows."
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
package/src/ci/schema.ts
ADDED
package/src/collection.json
CHANGED
|
@@ -6,6 +6,11 @@
|
|
|
6
6
|
"factory": "./ng-add/index#ngAdd",
|
|
7
7
|
"schema": "./ng-add/schema.json"
|
|
8
8
|
},
|
|
9
|
+
"ci": {
|
|
10
|
+
"description": "Generates a GitHub Actions CI workflow using existing package scripts.",
|
|
11
|
+
"factory": "./ci/index#ci",
|
|
12
|
+
"schema": "./ci/schema.json"
|
|
13
|
+
},
|
|
9
14
|
"accordion": {
|
|
10
15
|
"description": "Generates a standalone Angular Accordion component following the W3C ARIA Authoring Practices Guide.",
|
|
11
16
|
"factory": "./accordion/index#accordion",
|