Skip to content

Commit

Permalink
feat: add theme ai
Browse files Browse the repository at this point in the history
  • Loading branch information
Justineo committed Dec 27, 2023
1 parent 37091c2 commit 7d72a63
Show file tree
Hide file tree
Showing 8 changed files with 243 additions and 20 deletions.
31 changes: 30 additions & 1 deletion packages/less-plugin-dls/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ With [less-loader](https://github.com/webpack-contrib/less-loader):
```less
@import "~less-plugin-dls/tokens/index.less";

a { color: @dls-link-font-color-normal; }
a {
color: @dls-link-font-color-normal;
}
```

### Use CLI argument
Expand All @@ -41,6 +43,29 @@ a { color: @dls-link-font-color-normal; }
lessc style.less --dls
```

## Using metadata

Variable values/metadata are provided in three formats for each theme.

| File | Description |
| -- | -- |
| `variables.js` | The raw variable values in JavaScript ESM format. Token names are transformed from `@dls-color-brand-7` to `dlsColorBrand7` as named exports. |
| `variables.json` | The raw variable values in JSON format. |
| `variables.less` | The variable values in Less format. |

```ts
// types for the JSON format:
interface Variables {
[tokenName: string]: {
value: string
type: 'color' | 'font' | 'numeric' | 'length' | 'complex'
global: boolean
}
}
```

There are also themed versions of the above files, which are named with the theme name as the suffix, namely `variables.<theme>.js`, `variables.<theme>.json` and `variables.<theme>.less`. Currently the only supported theme is `ai`.

## Custom functions

### `dls-contextual(@color, @type)`
Expand Down Expand Up @@ -138,6 +163,10 @@ The absolute length of the line-height.

## Options

### `theme: 'ai' | undefined`

The theme of the DLS. If not specified, the default theme will be used.

### `reduceCalc: boolean`

Indicates whether to reduce `calc` expression to the simplest form or not.
Expand Down
15 changes: 12 additions & 3 deletions packages/less-plugin-dls/lib/utils/evaluate.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@ import { VariablesOutputVisitor } from './visitors'
const SELECTOR = 'DLS_VARS'

export async function getVariables(path) {
if (!fs.existsSync(path)) {
return []
}

const visitor = new VariablesOutputVisitor()

await less.render(fs.readFileSync(path, 'utf-8'), {
filename: path,
plugins: [
dls({
inject: false
Expand All @@ -25,15 +30,15 @@ export async function getVariables(path) {
return visitor.variables.map((v) => v.slice(1))
}

export async function getTuples(variables) {
export async function getTuples(variables, { theme }) {
const src = [
`${SELECTOR}{`,
variables.map((v) => `${v}: @${v}`).join(';'),
dedupe(variables).map((v) => `${v}: @${v}`).join(';'),
'}'
].join('')

const { css } = await less.render(src, {
plugins: [dls()]
plugins: [dls({ theme })]
})

return css
Expand All @@ -43,3 +48,7 @@ export async function getTuples(variables) {
.filter((v) => v)
.map((decl) => decl.split(/:\s*/))
}

function dedupe (arr) {
return Array.from(new Set(arr))
}
24 changes: 17 additions & 7 deletions packages/less-plugin-dls/scripts/vars.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,27 @@ import camelCase from 'lodash.camelcase'
import { parse } from 'postcss-values-parser'
import { getVariables, getTuples } from '../lib/utils/evaluate'

async function generate() {
async function generate({ theme } = {}) {
try {
const allVariables = await getVariables('./tokens/index.less')
const globalVariables = await getVariables('./tokens/global.less')
const themeVariables = await getVariables(`./tokens/themes/${theme}.less`)

const tuples = await getTuples(allVariables)
const tuples = await getTuples(allVariables.concat(themeVariables), {
theme
})

const themeTail = theme ? `.${theme}` : ''

// generate variables.less
fs.writeFileSync(
path.resolve(__dirname, '..', 'variables.less'),
path.resolve(__dirname, '..', `variables${themeTail}.less`),
tuples.map(([key, value]) => `@${key}: ${value};`).join('\n') + '\n',
'utf8'
)

fs.writeFileSync(
path.resolve(__dirname, '..', 'variables.js'),
path.resolve(__dirname, '..', `variables${themeTail}.js`),
tuples
.map(([key, value]) => `export const ${camelCase(key)} = '${value}'`)
.join('\n') + '\n',
Expand All @@ -28,7 +33,7 @@ async function generate() {

// generate variables.json
fs.writeFileSync(
path.resolve(__dirname, '..', 'variables.json'),
path.resolve(__dirname, '..', `variables${themeTail}.json`),
JSON.stringify(
tuples
.map(([key, value]) => ({
Expand All @@ -48,7 +53,7 @@ async function generate() {
'utf8'
)

console.log(`${tuples.length} variables generated.`)
console.log(`${tuples.length} variables generated for theme [${theme || 'default'}].`)
} catch (e) {
console.error(e)
}
Expand Down Expand Up @@ -129,4 +134,9 @@ function getTypeByValue(value) {
return 'unknown'
}

generate()
async function run() {
await generate()
await generate({ theme: 'ai' })
}

run()
25 changes: 22 additions & 3 deletions packages/less-plugin-dls/src/inject.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import path from 'path'
import fs from 'fs'

const SELF_MODULE_PATH = path.resolve(__dirname, '..')
const ENTRY_LESS = path.resolve(__dirname, '../tokens/index.less')
const THEME_DIR = path.resolve(__dirname, '../tokens/themes')

class Injector {
constructor ({ theme }) {
this.theme = theme
}

process(src, extra) {
// Don't inject self
if (
Expand All @@ -19,11 +25,24 @@ class Injector {
path.dirname(extra.fileInfo.filename),
ENTRY_LESS
)

const themeLess = path.resolve(THEME_DIR, `${this.theme}.less`)
let themeRelative = fs.existsSync(themeLess) ? path.relative(
path.dirname(extra.fileInfo.filename),
themeLess
) : null

// less requires relative path to starts with ./
if (relative.charAt(0) !== '.') {
relative = `./${relative}`
}
const injected = `@import "${relative}";\n`
if (themeRelative && themeRelative.charAt(0) !== '.') {
themeRelative = `./${themeRelative}`
}

let injected = `@import "${relative}";\n`
injected += themeRelative ? `@import "${themeRelative}";\n` : ''

const ignored = extra.imports.contentsIgnoredChars
const fileInfo = extra.fileInfo
ignored[fileInfo.filename] = ignored[fileInfo.filename] || 0
Expand All @@ -33,9 +52,9 @@ class Injector {
}

export default function inject(_, pluginManager) {
const { inject = true } = this.options || {}
const { inject = true, theme } = this.options || {}

if (inject) {
pluginManager.addPreProcessor(new Injector())
pluginManager.addPreProcessor(new Injector({ theme }))
}
}
18 changes: 12 additions & 6 deletions packages/less-plugin-dls/test/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const INCLUDE_PATH = path.resolve(__dirname, '../src')
const SPEC_DIR = path.resolve(__dirname, 'specs')
const SRC_DIR = path.resolve(__dirname, '../tokens')
const SRC_COMPONENTS_DIR = path.resolve(SRC_DIR, 'components')
const MANUAL_SPEC_MODULES = ['functions', 'global']
const MANUAL_SPEC_MODULES = ['functions', 'global', 'ai']
const VAR_DEF_RE = /@([a-z]+(?:-[a-z0-9]+)*)\s*:/g

function extractVarDefs (file) {
Expand Down Expand Up @@ -114,11 +114,16 @@ function getTests () {
}

const specFile = path.resolve(moduleDir, partFile)
if (args['--update-snapshots']) {
const srcFile = !MANUAL_SPEC_MODULES.includes(module)
? path.resolve(SRC_COMPONENTS_DIR, module + '.less')
: module === 'global' ? path.resolve(SRC_DIR, 'global.less') : null

const srcFile = !MANUAL_SPEC_MODULES.includes(module)
? path.resolve(SRC_COMPONENTS_DIR, module + '.less')
: module === 'global'
? path.resolve(SRC_DIR, 'global.less')
: module === 'ai'
? path.resolve(SRC_DIR, 'themes/ai.less')
: null

if (args['--update-snapshots']) {
if (srcFile) {
const vars = extractVarDefs(srcFile)
if (vars.length) {
Expand All @@ -138,6 +143,7 @@ function getTests () {
module,
part,
src,
theme: module === 'ai' ? 'ai' : null,
expected
})
}
Expand Down Expand Up @@ -165,7 +171,7 @@ function getSuite (name, tests, { less }) {
.render(test.src, {
paths: [INCLUDE_PATH],
javascriptEnabled: true,
plugins: [dls()]
plugins: [dls({ theme: test.theme })]
})
.then(
result => {
Expand Down
46 changes: 46 additions & 0 deletions packages/less-plugin-dls/test/specs/ai/ai.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
div {
-dls-color-brand: #4d79ff;
-dls-color-brand-0: #fff;
-dls-color-brand-1: #f2f7ff;
-dls-color-brand-2: #e3edff;
-dls-color-brand-3: #c4daff;
-dls-color-brand-4: #99beff;
-dls-color-brand-5: #729cfe;
-dls-color-brand-6: #4d79ff;
-dls-color-brand-7: #3a5bfd;
-dls-color-brand-8: #333fe6;
-dls-color-brand-9: #0f2dbd;
-dls-color-brand-10: #1c244a;
-dls-color-brand-11: #000;
-dls-color-info: #4d79ff;
-dls-color-info-0: #fff;
-dls-color-info-1: #f2f7ff;
-dls-color-info-2: #e3edff;
-dls-color-info-3: #c4daff;
-dls-color-info-4: #99beff;
-dls-color-info-5: #729cfe;
-dls-color-info-6: #4d79ff;
-dls-color-info-7: #3a5bfd;
-dls-color-info-8: #333fe6;
-dls-color-info-9: #0f2dbd;
-dls-color-info-10: #1c244a;
-dls-color-info-11: #000;
-dls-color-success: #3ac222;
-dls-color-warning: #fea800;
-dls-color-error: #f53f3f;
-dls-height-xs: 28px;
-dls-height-s: 32px;
-dls-height-m: 36px;
-dls-height-l: 40px;
-dls-height-xl: 48px;
-dls-border-radius-0: 4px;
-dls-border-radius-1: 6px;
-dls-border-radius-2: 10px;
-dls-border-radius-3: 16px;
-dls-border-radius-4: 26px;
-dls-shadow-color: #0047c2;
-dls-checkbox-border-radius: 4px;
-dls-tag-color-turquoise: #00bbd1;
-dls-tag-color-violet: #824fe7;
-dls-tag-color-green: #3ac222;
}
46 changes: 46 additions & 0 deletions packages/less-plugin-dls/test/specs/ai/ai.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
div {
-dls-color-brand: @dls-color-brand;
-dls-color-brand-0: @dls-color-brand-0;
-dls-color-brand-1: @dls-color-brand-1;
-dls-color-brand-2: @dls-color-brand-2;
-dls-color-brand-3: @dls-color-brand-3;
-dls-color-brand-4: @dls-color-brand-4;
-dls-color-brand-5: @dls-color-brand-5;
-dls-color-brand-6: @dls-color-brand-6;
-dls-color-brand-7: @dls-color-brand-7;
-dls-color-brand-8: @dls-color-brand-8;
-dls-color-brand-9: @dls-color-brand-9;
-dls-color-brand-10: @dls-color-brand-10;
-dls-color-brand-11: @dls-color-brand-11;
-dls-color-info: @dls-color-info;
-dls-color-info-0: @dls-color-info-0;
-dls-color-info-1: @dls-color-info-1;
-dls-color-info-2: @dls-color-info-2;
-dls-color-info-3: @dls-color-info-3;
-dls-color-info-4: @dls-color-info-4;
-dls-color-info-5: @dls-color-info-5;
-dls-color-info-6: @dls-color-info-6;
-dls-color-info-7: @dls-color-info-7;
-dls-color-info-8: @dls-color-info-8;
-dls-color-info-9: @dls-color-info-9;
-dls-color-info-10: @dls-color-info-10;
-dls-color-info-11: @dls-color-info-11;
-dls-color-success: @dls-color-success;
-dls-color-warning: @dls-color-warning;
-dls-color-error: @dls-color-error;
-dls-height-xs: @dls-height-xs;
-dls-height-s: @dls-height-s;
-dls-height-m: @dls-height-m;
-dls-height-l: @dls-height-l;
-dls-height-xl: @dls-height-xl;
-dls-border-radius-0: @dls-border-radius-0;
-dls-border-radius-1: @dls-border-radius-1;
-dls-border-radius-2: @dls-border-radius-2;
-dls-border-radius-3: @dls-border-radius-3;
-dls-border-radius-4: @dls-border-radius-4;
-dls-shadow-color: @dls-shadow-color;
-dls-checkbox-border-radius: @dls-checkbox-border-radius;
-dls-tag-color-turquoise: @dls-tag-color-turquoise;
-dls-tag-color-violet: @dls-tag-color-violet;
-dls-tag-color-green: @dls-tag-color-green;
}
Loading

0 comments on commit 7d72a63

Please sign in to comment.