Skip to content

Commit

Permalink
[cascading] from release/11.1.0-rc to main (#2028)
Browse files Browse the repository at this point in the history
<!--
{"currentBranch":"release/11.1.0-rc","targetBranch":"main","bypassReviewers":true,"isConflicting":false}
-->

## Cascading from release/11.1.0-rc to main

The configuration requests the cascading to bypass reviewer in case of
CI success.
To not bypass the reviewing process, please check the following
checkbox:

- [ ] <!-- !cancel bypass! --> 🚫 stop reviewing process
bypass for this Pull Request

---

<small>This Pull Request has been generated with ❤️ by the
[Otter](https://github.com/AmadeusITGroup/otter) cascading tool.</small>
  • Loading branch information
kpanot authored Aug 6, 2024
2 parents e2a7d4d + 66c55a9 commit 27d7e7f
Show file tree
Hide file tree
Showing 16 changed files with 225 additions and 29 deletions.
60 changes: 59 additions & 1 deletion docs/design/TECHNICAL_DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,67 @@ Both of these features can be customized at different levels. They can be custom

### Parsers

Currently the [o3r/design](https://github.com/AmadeusITGroup/otter/tree/main/packages/@o3r/design) package provides only a single [parser](https://github.com/AmadeusITGroup/otter/tree/main/packages/@o3r/design/src/core/design-token/parsers).
Currently the [@o3r/design](https://github.com/AmadeusITGroup/otter/tree/main/packages/@o3r/design) package provides only a single [parser](https://github.com/AmadeusITGroup/otter/tree/main/packages/@o3r/design/src/core/design-token/parsers).
This parser handles Design Token specifications (as a JSON file or a loaded object resulting from the parsing of a JSON file) to generate an object facilitating the tree navigation and the value computed by the renderers.

#### Template feature

In addition of parsing Design Token specifications, the parser also offers the feature to enhance the specifications thanks to a *template* that can be provided via the parser context.
The purpose of the *template* is to provide default values to `$extensions` and `$description` to any nodes of the specification.

Example:

```json5
// The template to apply (at application/library level):
{
"color": {
"$extension": {
"o3rMetadata": {
"category": "theming" // set the property o3rMetadata.category to "theming" for all `color.*` tokens
}
},
"background": {
"$extension": {
"o3rPrivate": true // will turn the `color.background.*` tokens to private
}
}
}
}
```

when applied to the following Design Token specification:

```json5
{
"color.primary.500": { // will inherit of `o3rPrivate: true` and `o3rMetadata.category: "theming"`
"$value": "#aaa"
},
"color.secondary.500": { // will inherit of `o3rPrivate: true` only
"$value": "#aaa",
"$extension": {
"o3rMetadata": {
"category": "supp"
}
}
},
"color.ternary.500": { // will not be changed
"$value": "#aaa",
"$extension": {
"private": false,
"o3rMetadata": {
"category": "supp"
}
}
},
"sizing.spacer.10": { // will not be changed`
"$value": "64px"
},
}
```

> [!TIP]
> When using the [generate-css builder](https://github.com/AmadeusITGroup/otter/blob/main/packages/%40o3r/design/README.md#generate-css), the *template* can be provided as JSON file via the **templateFile** option.
### Renderers

The package exposes 3 renderers:
Expand Down
2 changes: 2 additions & 0 deletions packages/@o3r/design/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ The following configurations are available:
| **metadataOutput** | *null* | Path to generate the metadata for the CMS. <br /> The metadata will be generated only if the file path is specified. |
| **rootPath** | *null* | Root path of files where the CSS will be generated. |
| **failOnDuplicate** | false | Determine if the process should stop in case of Token duplication. |
| **templateFile** | *null* | Path to a template file to apply as default configuration to a Design Token extension. |
| **prefix** | *null* | Prefix to append to generated variables. |
| **prefixPrivate** | *null* | Prefix to append to generated private variables. |
| **watch** | false | Enable Watch mode. |

### generate-jsonschema
Expand Down
11 changes: 8 additions & 3 deletions packages/@o3r/design/builders/generate-css/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import {
renderDesignTokens,
tokenVariableNameSassRenderer
} from '../../src/public_api';
import type { DesignTokenRendererOptions, DesignTokenVariableSet, DesignTokenVariableStructure, TokenKeyRenderer } from '../../src/public_api';
import type { DesignTokenGroupTemplate, DesignTokenRendererOptions, DesignTokenVariableSet, DesignTokenVariableStructure, TokenKeyRenderer } from '../../src/public_api';
import { resolve } from 'node:path';
import * as globby from 'globby';
import { EOL } from 'node:os';
import { readFile } from 'node:fs/promises';

/**
* Generate CSS from Design Token files
Expand Down Expand Up @@ -68,6 +69,7 @@ export default createBuilder<GenerateCssSchematicsSchema>(async (options, contex
};

const execute = async (renderDesignTokenOptions: DesignTokenRendererOptions): Promise<BuilderOutput> => {
const template = options.templateFile ? JSON.parse(await readFile(resolve(context.workspaceRoot, options.templateFile), { encoding: 'utf-8' })) as DesignTokenGroupTemplate : undefined;
const files = (await globby(designTokenFilePatterns, { cwd: context.workspaceRoot, absolute: true }));

const inDependencies = designTokenFilePatterns
Expand All @@ -84,7 +86,7 @@ export default createBuilder<GenerateCssSchematicsSchema>(async (options, contex

try {
const duplicatedToken: DesignTokenVariableStructure[] = [];
const tokens = (await Promise.all(files.map(async (file) => ({file, parsed: await parseDesignTokenFile(file)}))))
const tokens = (await Promise.all(files.map(async (file) => ({file, parsed: await parseDesignTokenFile(file, { specificationContext: { template } })}))))
.reduce<DesignTokenVariableSet>((acc, {file, parsed}) => {
parsed.forEach((variable, key) => {
if (acc.has(key)) {
Expand Down Expand Up @@ -133,7 +135,10 @@ export default createBuilder<GenerateCssSchematicsSchema>(async (options, contex
} else {
try {
await import('chokidar')
.then((chokidar) => chokidar.watch(designTokenFilePatterns.map((p) => resolve(context.workspaceRoot, p))))
.then((chokidar) => chokidar.watch([
...designTokenFilePatterns.map((p) => resolve(context.workspaceRoot, p)),
...(options.templateFile ? [resolve(context.workspaceRoot, options.templateFile)] : [])
]))
.then((watcher) => watcher.on('all', async () => {
const res = await executeMultiRenderer();

Expand Down
8 changes: 6 additions & 2 deletions packages/@o3r/design/builders/generate-css/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,17 @@
"default": false,
"description": "Determine if the process should stop in case of Token duplication"
},
"templateFile": {
"type": "string",
"description": "Path to a template file to apply as default configuration to a Design Token extension"
},
"prefix": {
"type": "string",
"description": "Prefix to happen to generated variables"
"description": "Prefix to append to generated variables"
},
"prefixPrivate": {
"type": "string",
"description": "Prefix to happen to generated Sass variables if generated"
"description": "Prefix to append to generated private variables"
},
"renderPrivateVariableTo": {
"type": "string",
Expand Down
5 changes: 4 additions & 1 deletion packages/@o3r/design/builders/generate-css/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,15 @@ export interface GenerateCssSchematicsSchema extends SchematicOptionObject {
/** Generate the Private Variable to the given language */
renderPrivateVariableTo?: 'sass';

/** Prefix to happen to generated Sass variables if generated */
/** Prefix to happen to generated private variables */
prefixPrivate?: string;

/** Determine if the builder should fail if a missing Design Token reference is detected */
failOnMissingReference?: boolean;

/** Type of the variables to generate for a Design Token */
variableType?: 'css' | 'sass';

/** Path to a template file to apply as default configuration to a Design Token extension */
templateFile?: string;
}
4 changes: 2 additions & 2 deletions packages/@o3r/design/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
"nx": "nx",
"ng": "yarn nx",
"test": "yarn nx test design",
"copy:templates": "yarn cpy 'schematics/**/templates/**/*' dist/schematics",
"copy:templates": "yarn cpy 'schematics/**/templates{-*,}/**/*' dist/schematics && yarn cpy 'builders/**/templates/**/*' dist/builders",
"copy:schemas": "yarn cpy 'schemas/**/*' dist/schemas",
"prepare:build:builders": "yarn cpy 'builders/**/*.json' dist/builders && yarn cpy '{builders,collection,migration}.json' dist && yarn cpy 'schematics/**/*.json' dist/schematics && yarn copy:templates",
"prepare:build:builders": "yarn cpy 'builders/**/schema.json' dist/builders && yarn cpy '{builders,collection,migration}.json' dist && yarn cpy 'schematics/**/schema.json' dist/schematics && yarn copy:templates",
"prepare:publish": "prepare-publish ./dist",
"build:source": "tsc -b tsconfig.build.json && yarn cpy package.json dist/",
"build:builders": "tsc -b tsconfig.builders.json --pretty && yarn copy:templates && generate-cjs-manifest",
Expand Down
32 changes: 32 additions & 0 deletions packages/@o3r/design/schemas/design-token-template.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "DesignTokenTemplateSchema",
"description": "Schema Describing the structure of the Design Token template, to enhance a Design Token structure",
"allOf": [
{
"$ref": "#/definitions/tokenTemplateGroup"
}
],
"definitions": {
"tokenTemplateGroup": {
"type": "object",
"properties": {
"$schema": {
"type": "string"
},
"$description": {
"type": "string"
},
"$extensions": {
"$ref": "https://raw.githubusercontent.com/AmadeusITGroup/otter/main/packages/%40o3r/design/schemas/design-token.schema.json#/definitions/extensions"
}
},
"patternProperties": {
"^[^$.].*$": {
"$ref": "#/definitions/tokenTemplateGroup"
}
},
"additionalProperties": false
}
}
}
1 change: 1 addition & 0 deletions packages/@o3r/design/schematics/index.it.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ describe('new otter application with Design', () => {
expect(diff.modified).toContain('angular.json');
expect(diff.added).toContain(path.posix.join('apps', appName, 'src/style/design-token.custom.json'));
expect(diff.added).toContain(path.posix.join('apps', appName, 'src/style/theme.scss'));
expect(diff.added).toContain(path.posix.join('apps', appName, 'design-token.template.json'));

untouchedProjectsPaths.forEach(untouchedProject => {
expect(diff.all.some(file => file.startsWith(path.posix.relative(workspacePath, untouchedProject)))).toBe(false);
Expand Down
1 change: 1 addition & 0 deletions packages/@o3r/design/schematics/ng-add/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ describe('ng-add', () => {
}, initialTree);

expect(tree.exists('src/style/design-token.custom.json')).toBe(true);
expect(tree.exists('design-token.template.json')).toBe(true);
expect(tree.exists('src/style/theme.scss')).toBe(true);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ export const registerGenerateCssBuilder = (projectName?: string, taskName = 'gen
const { getWorkspaceConfig, registerBuilder } = await import('@o3r/schematics');
const workspace = getWorkspaceConfig(tree);
const workspaceProject = projectName ? workspace?.projects[projectName] : undefined;
const srcBasePath = workspaceProject?.sourceRoot || (workspaceProject?.root ? posix.join(workspaceProject.root, 'src') : './src');
const workspaceRootPath = workspaceProject?.root || '.';
const srcBasePath = workspaceProject?.sourceRoot || posix.join(workspaceRootPath, 'src');
const themeFile = posix.join(srcBasePath, 'style', 'theme.scss');
const taskOptions: GenerateCssSchematicsSchema = {
defaultStyleFile: themeFile,
renderPrivateVariableTo: 'sass',
templateFile: posix.join(workspaceRootPath, 'design-token.template.json'),
designTokenFilePatterns: [
`${posix.join(srcBasePath, 'style', '*.json')}`,
`${posix.join(srcBasePath, '**', '*.theme.json')}`
posix.join(srcBasePath, 'style', '*.json'),
posix.join(srcBasePath, '**', '*.theme.json')
]
};
const taskParameters = {
Expand All @@ -36,7 +38,7 @@ export const registerGenerateCssBuilder = (projectName?: string, taskName = 'gen
tree.overwrite('/angular.json', JSON.stringify(workspace, null, 2));
};

const generateTemplateRule: Rule = async (tree) => {
const generateDesignTokenFilesRule: Rule = async (tree) => {
const { getWorkspaceConfig } = await import('@o3r/schematics');
const workspaceProject = projectName ? getWorkspaceConfig(tree)?.projects[projectName] : undefined;
const srcBasePath = workspaceProject?.sourceRoot || (workspaceProject?.root ? posix.join(workspaceProject.root, 'src') : './src');
Expand All @@ -48,6 +50,17 @@ export const registerGenerateCssBuilder = (projectName?: string, taskName = 'gen
]), MergeStrategy.Overwrite);
};

const generateTemplateFilesRule: Rule = async (tree) => {
const { getWorkspaceConfig } = await import('@o3r/schematics');
const workspaceProject = projectName ? getWorkspaceConfig(tree)?.projects[projectName] : undefined;
const workspaceRootPath = workspaceProject?.root || '.';
return mergeWith(apply(url('./register-generate-css/templates-workspace'), [
template({}),
renameTemplateFiles(),
move(workspaceRootPath)
]), MergeStrategy.Overwrite);
};

const importTheme: Rule = async (tree, context) => {
const { getWorkspaceConfig } = await import('@o3r/schematics');
const workspaceProject = projectName ? getWorkspaceConfig(tree)?.projects[projectName] : undefined;
Expand All @@ -62,7 +75,8 @@ export const registerGenerateCssBuilder = (projectName?: string, taskName = 'gen

return chain([
registerBuilderRule,
generateTemplateRule,
generateDesignTokenFilesRule,
generateTemplateFilesRule,
importTheme
]);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"$schema": "https://raw.githubusercontent.com/AmadeusITGroup/otter/main/packages/@o3r/design/schemas/design-token-template.schema.json"
}
Original file line number Diff line number Diff line change
Expand Up @@ -239,10 +239,17 @@ export type DesignTokenNode<E extends DesignTokenExtensions = DesignTokenExtensi
export type DesignTokenGroup<E extends DesignTokenExtensions = DesignTokenExtensions, G extends DesignTokenGroupExtensions = E> =
DesignTokenGroupCommonFields<G> & { [x: string]: DesignTokenNode<E, G> | E | string | boolean | undefined };

/** Design Token Group for common properties only */
export type DesignTokenGroupTemplate<G extends DesignTokenGroupExtensions = DesignTokenGroupExtensions> =
DesignTokenGroupCommonFields<G> & { [x: string]: DesignTokenGroupTemplate<DesignTokenGroupExtensions> | G | string | boolean | undefined };

/** Context of the Design Token specification document */
export type DesignTokenContext = {
export type DesignTokenContext<G extends DesignTokenGroupExtensions = DesignTokenGroupExtensions> = {
/** Base path used to compute the path of the file to render the Tokens into */
basePath?: string;

/** Default template of the Design Token nodes to use as base for the extension configuration */
template?: DesignTokenGroupTemplate<G>;
};

/** Design Token specification */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import type { DesignToken, DesignTokenContext, DesignTokenExtensions, DesignTokenGroup, DesignTokenGroupExtensions } from '../design-token-specification.interface';

/** Reference to a parent node*/
/** Reference to a parent node */
export interface ParentReference {
/** Design Token name */
name: string;
/** Design Token Group node */
tokenNode: DesignTokenGroup;
}

/** Reference to a node */
export interface NodeReference {
/** Design Token name */
name: string;
/** Design Token Group node */
tokenNode: DesignTokenGroup | DesignToken;
}

/**
* Function rendering the Design Token Value
* @param tokenStructure Parsed Design Token
Expand Down
Loading

0 comments on commit 27d7e7f

Please sign in to comment.