@servicetitan/stylelint-config 40.1.0 → 40.2.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/dist/function-url-no-absolute.d.ts.map +1 -1
- package/dist/function-url-no-absolute.js +1 -7
- package/dist/function-url-no-absolute.js.map +1 -1
- package/dist/use-tokens/index.d.ts +2 -7
- package/dist/use-tokens/index.d.ts.map +1 -1
- package/dist/use-tokens/index.js +2 -114
- package/dist/use-tokens/index.js.map +1 -1
- package/dist/use-tokens/load-tokens.d.ts +11 -0
- package/dist/use-tokens/load-tokens.d.ts.map +1 -0
- package/dist/use-tokens/load-tokens.js +97 -0
- package/dist/use-tokens/load-tokens.js.map +1 -0
- package/dist/use-tokens/use-tokens.d.ts +9 -0
- package/dist/use-tokens/use-tokens.d.ts.map +1 -0
- package/dist/use-tokens/use-tokens.js +169 -0
- package/dist/use-tokens/use-tokens.js.map +1 -0
- package/dist/use-tokens/values.d.ts +11 -9
- package/dist/use-tokens/values.d.ts.map +1 -1
- package/dist/use-tokens/values.js +59 -22
- package/dist/use-tokens/values.js.map +1 -1
- package/package.json +12 -4
- package/src/__tests__/function-url-no-absolute.test.ts +84 -0
- package/src/function-url-no-absolute.ts +1 -2
- package/src/use-tokens/__tests__/load-tokens.test.ts +135 -0
- package/src/use-tokens/__tests__/use-tokens.test.ts +414 -0
- package/src/use-tokens/index.ts +2 -162
- package/src/use-tokens/load-tokens.ts +103 -0
- package/src/use-tokens/use-tokens.ts +214 -0
- package/src/use-tokens/values.ts +55 -37
|
@@ -37,34 +37,71 @@ _export(exports, {
|
|
|
37
37
|
return zIndexes;
|
|
38
38
|
}
|
|
39
39
|
});
|
|
40
|
-
const _core = require("@servicetitan/tokens/core");
|
|
41
40
|
const _color = /*#__PURE__*/ _interop_require_default(require("color"));
|
|
42
|
-
const
|
|
41
|
+
const _loadtokens = require("./load-tokens");
|
|
43
42
|
function _interop_require_default(obj) {
|
|
44
43
|
return obj && obj.__esModule ? obj : {
|
|
45
44
|
default: obj
|
|
46
45
|
};
|
|
47
46
|
}
|
|
48
|
-
const
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
47
|
+
const tokens = (0, _loadtokens.loadTokens)();
|
|
48
|
+
const colors = getValues({
|
|
49
|
+
[_loadtokens.DESIGN_SYSTEM_SOURCE]: /^color/,
|
|
50
|
+
[_loadtokens.ANVIL2_SOURCE]: /^color-/
|
|
51
|
+
}, (value)=>new _color.default(value).hexa());
|
|
52
|
+
const typescales = getValues({
|
|
53
|
+
[_loadtokens.DESIGN_SYSTEM_SOURCE]: /^typescale/,
|
|
54
|
+
[_loadtokens.ANVIL2_SOURCE]: /^font-size-/
|
|
55
|
+
});
|
|
56
|
+
const borderRadiuses = getValues({
|
|
57
|
+
[_loadtokens.DESIGN_SYSTEM_SOURCE]: /^border-radius/,
|
|
58
|
+
[_loadtokens.ANVIL2_SOURCE]: /^radius-/
|
|
59
|
+
});
|
|
60
|
+
const spacings = getValues({
|
|
61
|
+
[_loadtokens.DESIGN_SYSTEM_SOURCE]: /^spacing/,
|
|
62
|
+
[_loadtokens.ANVIL2_SOURCE]: /^size-/
|
|
63
|
+
});
|
|
64
|
+
const fontWeights = getValues({
|
|
65
|
+
[_loadtokens.DESIGN_SYSTEM_SOURCE]: /^font-weight/,
|
|
66
|
+
[_loadtokens.ANVIL2_SOURCE]: /^font-weight-/
|
|
67
|
+
});
|
|
68
|
+
const opacities = getValues({
|
|
69
|
+
[_loadtokens.DESIGN_SYSTEM_SOURCE]: /^opacity/
|
|
70
|
+
});
|
|
71
|
+
const zIndexes = getValues({
|
|
72
|
+
[_loadtokens.DESIGN_SYSTEM_SOURCE]: /^z-index/
|
|
73
|
+
});
|
|
74
|
+
const lineHeights = getValues({
|
|
75
|
+
[_loadtokens.DESIGN_SYSTEM_SOURCE]: /-line-height$/,
|
|
76
|
+
[_loadtokens.ANVIL2_SOURCE]: /^font-line-height-/
|
|
77
|
+
});
|
|
78
|
+
const fontFamilies = getValues({
|
|
79
|
+
[_loadtokens.DESIGN_SYSTEM_SOURCE]: /-font-family$/,
|
|
80
|
+
[_loadtokens.ANVIL2_SOURCE]: /^font-family-/
|
|
81
|
+
}, (value)=>value.replace(/'/g, "'"));
|
|
82
|
+
function getValues(patterns, transformer) {
|
|
83
|
+
return tokens.reduce((result, token)=>{
|
|
84
|
+
var _result_get;
|
|
85
|
+
var _patterns_token_source;
|
|
86
|
+
if (!((_patterns_token_source = patterns[token.source]) === null || _patterns_token_source === void 0 ? void 0 : _patterns_token_source.test(token.name))) {
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
/*
|
|
90
|
+
* A token the transformer can't normalize, such as an oklch() color, can never match a
|
|
91
|
+
* literal, so it's skipped rather than failing every lint run.
|
|
92
|
+
*/ let value;
|
|
93
|
+
try {
|
|
94
|
+
var _ref;
|
|
95
|
+
value = (_ref = transformer === null || transformer === void 0 ? void 0 : transformer(token.value)) !== null && _ref !== void 0 ? _ref : token.value;
|
|
96
|
+
} catch (unused) {
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
/* Within a source, the last token with a given value wins. */ const matches = ((_result_get = result.get(value)) !== null && _result_get !== void 0 ? _result_get : []).filter(({ source })=>source !== token.source);
|
|
100
|
+
return result.set(value, [
|
|
101
|
+
...matches,
|
|
102
|
+
token
|
|
103
|
+
]);
|
|
104
|
+
}, new Map());
|
|
59
105
|
}
|
|
60
|
-
const colors = getValues((variable)=>variable.startsWith('color'), (value)=>new _color.default(value).hex());
|
|
61
|
-
const typescales = getValues((variable)=>variable.startsWith('typescale'));
|
|
62
|
-
const borderRadiuses = getValues((variable)=>variable.startsWith('borderRadius'));
|
|
63
|
-
const spacings = getValues((variable)=>variable.startsWith('spacing'));
|
|
64
|
-
const fontWeights = getValues((variable)=>variable.startsWith('fontWeight'));
|
|
65
|
-
const opacities = getValues((variable)=>variable.startsWith('opacity'));
|
|
66
|
-
const zIndexes = getValues((variable)=>variable.startsWith('zIndex'));
|
|
67
|
-
const lineHeights = getValues((variable)=>variable.endsWith('LineHeight'));
|
|
68
|
-
const fontFamilies = getValues((variable)=>variable.endsWith('FontFamily'), (value)=>value.replace(/'/g, "'"));
|
|
69
106
|
|
|
70
107
|
//# sourceMappingURL=values.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/use-tokens/values.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["../../src/use-tokens/values.ts"],"sourcesContent":["import Color from 'color';\nimport { ANVIL2_SOURCE, DESIGN_SYSTEM_SOURCE, Token, TokenSource, loadTokens } from './load-tokens';\n\n/* Maps a literal value to the tokens that hold it, at most one per source. */\nexport type TokenCollection = Map<string, Token[]>;\n\nconst tokens = loadTokens();\n\nexport const colors = getValues(\n { [DESIGN_SYSTEM_SOURCE]: /^color/, [ANVIL2_SOURCE]: /^color-/ },\n value => new Color(value).hexa()\n);\nexport const typescales = getValues({\n [DESIGN_SYSTEM_SOURCE]: /^typescale/,\n [ANVIL2_SOURCE]: /^font-size-/,\n});\nexport const borderRadiuses = getValues({\n [DESIGN_SYSTEM_SOURCE]: /^border-radius/,\n [ANVIL2_SOURCE]: /^radius-/,\n});\nexport const spacings = getValues({\n [DESIGN_SYSTEM_SOURCE]: /^spacing/,\n [ANVIL2_SOURCE]: /^size-/,\n});\nexport const fontWeights = getValues({\n [DESIGN_SYSTEM_SOURCE]: /^font-weight/,\n [ANVIL2_SOURCE]: /^font-weight-/,\n});\nexport const opacities = getValues({ [DESIGN_SYSTEM_SOURCE]: /^opacity/ });\nexport const zIndexes = getValues({ [DESIGN_SYSTEM_SOURCE]: /^z-index/ });\nexport const lineHeights = getValues({\n [DESIGN_SYSTEM_SOURCE]: /-line-height$/,\n [ANVIL2_SOURCE]: /^font-line-height-/,\n});\nexport const fontFamilies = getValues(\n { [DESIGN_SYSTEM_SOURCE]: /-font-family$/, [ANVIL2_SOURCE]: /^font-family-/ },\n value => value.replace(/'/g, \"'\")\n);\n\nfunction getValues(\n patterns: Partial<Record<TokenSource, RegExp>>,\n transformer?: (value: string) => string\n) {\n return tokens.reduce<TokenCollection>((result, token) => {\n if (!patterns[token.source]?.test(token.name)) {\n return result;\n }\n\n /*\n * A token the transformer can't normalize, such as an oklch() color, can never match a\n * literal, so it's skipped rather than failing every lint run.\n */\n let value: string;\n try {\n value = transformer?.(token.value) ?? token.value;\n } catch {\n return result;\n }\n\n /* Within a source, the last token with a given value wins. */\n const matches = (result.get(value) ?? []).filter(({ source }) => source !== token.source);\n return result.set(value, [...matches, token]);\n }, new Map());\n}\n"],"names":["borderRadiuses","colors","fontFamilies","fontWeights","lineHeights","opacities","spacings","typescales","zIndexes","tokens","loadTokens","getValues","DESIGN_SYSTEM_SOURCE","ANVIL2_SOURCE","value","Color","hexa","replace","patterns","transformer","reduce","result","token","source","test","name","matches","get","filter","set","Map"],"mappings":";;;;;;;;;;;QAgBaA;eAAAA;;QARAC;eAAAA;;QA0BAC;eAAAA;;QAVAC;eAAAA;;QAMAC;eAAAA;;QAFAC;eAAAA;;QARAC;eAAAA;;QARAC;eAAAA;;QAiBAC;eAAAA;;;8DA7BK;4BACkE;;;;;;AAKpF,MAAMC,SAASC,IAAAA,sBAAU;AAElB,MAAMT,SAASU,UAClB;IAAE,CAACC,gCAAoB,CAAC,EAAE;IAAU,CAACC,yBAAa,CAAC,EAAE;AAAU,GAC/DC,CAAAA,QAAS,IAAIC,cAAK,CAACD,OAAOE,IAAI;AAE3B,MAAMT,aAAaI,UAAU;IAChC,CAACC,gCAAoB,CAAC,EAAE;IACxB,CAACC,yBAAa,CAAC,EAAE;AACrB;AACO,MAAMb,iBAAiBW,UAAU;IACpC,CAACC,gCAAoB,CAAC,EAAE;IACxB,CAACC,yBAAa,CAAC,EAAE;AACrB;AACO,MAAMP,WAAWK,UAAU;IAC9B,CAACC,gCAAoB,CAAC,EAAE;IACxB,CAACC,yBAAa,CAAC,EAAE;AACrB;AACO,MAAMV,cAAcQ,UAAU;IACjC,CAACC,gCAAoB,CAAC,EAAE;IACxB,CAACC,yBAAa,CAAC,EAAE;AACrB;AACO,MAAMR,YAAYM,UAAU;IAAE,CAACC,gCAAoB,CAAC,EAAE;AAAW;AACjE,MAAMJ,WAAWG,UAAU;IAAE,CAACC,gCAAoB,CAAC,EAAE;AAAW;AAChE,MAAMR,cAAcO,UAAU;IACjC,CAACC,gCAAoB,CAAC,EAAE;IACxB,CAACC,yBAAa,CAAC,EAAE;AACrB;AACO,MAAMX,eAAeS,UACxB;IAAE,CAACC,gCAAoB,CAAC,EAAE;IAAiB,CAACC,yBAAa,CAAC,EAAE;AAAgB,GAC5EC,CAAAA,QAASA,MAAMG,OAAO,CAAC,WAAW;AAGtC,SAASN,UACLO,QAA8C,EAC9CC,WAAuC;IAEvC,OAAOV,OAAOW,MAAM,CAAkB,CAACC,QAAQC;YAiB1BD;YAhBZH;QAAL,IAAI,GAACA,yBAAAA,QAAQ,CAACI,MAAMC,MAAM,CAAC,cAAtBL,6CAAAA,uBAAwBM,IAAI,CAACF,MAAMG,IAAI,IAAG;YAC3C,OAAOJ;QACX;QAEA;;;SAGC,GACD,IAAIP;QACJ,IAAI;;YACAA,gBAAQK,wBAAAA,kCAAAA,YAAcG,MAAMR,KAAK,wCAAKQ,MAAMR,KAAK;QACrD,EAAE,eAAM;YACJ,OAAOO;QACX;QAEA,4DAA4D,GAC5D,MAAMK,UAAU,EAACL,cAAAA,OAAOM,GAAG,CAACb,oBAAXO,yBAAAA,cAAqB,EAAE,EAAEO,MAAM,CAAC,CAAC,EAAEL,MAAM,EAAE,GAAKA,WAAWD,MAAMC,MAAM;QACxF,OAAOF,OAAOQ,GAAG,CAACf,OAAO;eAAIY;YAASJ;SAAM;IAChD,GAAG,IAAIQ;AACX"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@servicetitan/stylelint-config",
|
|
3
|
-
"version": "40.
|
|
3
|
+
"version": "40.2.0",
|
|
4
4
|
"description": "Core Stylelint rule sets for ServiceTitan web projects",
|
|
5
5
|
"homepage": "https://docs.st.dev/docs/frontend/uikit/eslint-config",
|
|
6
6
|
"repository": {
|
|
@@ -17,22 +17,30 @@
|
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"color": "~5.0.3",
|
|
20
|
-
"lodash": "^4.18.1",
|
|
21
20
|
"stylelint-config-standard": "~40.0.0",
|
|
22
21
|
"stylelint-config-standard-less": "^4.1.0",
|
|
23
22
|
"stylelint-config-standard-scss": "^17.0.0",
|
|
24
23
|
"stylelint-prettier": "~5.0.3"
|
|
25
24
|
},
|
|
26
25
|
"devDependencies": {
|
|
26
|
+
"@servicetitan/anvil2": "^3.16.1",
|
|
27
27
|
"@servicetitan/tokens": "~12.9.0",
|
|
28
|
-
"
|
|
29
|
-
"stylelint": "~17.15.0"
|
|
28
|
+
"stylelint": "~17.16.0"
|
|
30
29
|
},
|
|
31
30
|
"peerDependencies": {
|
|
31
|
+
"@servicetitan/anvil2": ">=1.9.0",
|
|
32
32
|
"@servicetitan/tokens": ">=12",
|
|
33
33
|
"postcss": ">=8",
|
|
34
34
|
"stylelint": ">=16"
|
|
35
35
|
},
|
|
36
|
+
"peerDependenciesMeta": {
|
|
37
|
+
"@servicetitan/anvil2": {
|
|
38
|
+
"optional": true
|
|
39
|
+
},
|
|
40
|
+
"@servicetitan/tokens": {
|
|
41
|
+
"optional": true
|
|
42
|
+
}
|
|
43
|
+
},
|
|
36
44
|
"publishConfig": {
|
|
37
45
|
"access": "public"
|
|
38
46
|
},
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import postcss from 'postcss';
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* Stylelint is ESM-only, and Jest can only load ESM-only packages on Node 24.9+ with
|
|
5
|
+
* --experimental-vm-modules, so the rule runs directly against a postcss tree with stylelint's
|
|
6
|
+
* plugin utilities replaced.
|
|
7
|
+
*/
|
|
8
|
+
jest.mock('stylelint', () => ({
|
|
9
|
+
createPlugin: (ruleName: string, rule: unknown) => ({ ruleName, rule }),
|
|
10
|
+
utils: {
|
|
11
|
+
ruleMessages: (_ruleName: string, messages: unknown) => messages,
|
|
12
|
+
validateOptions: () => mockValidOptions,
|
|
13
|
+
report: mockReport,
|
|
14
|
+
},
|
|
15
|
+
}));
|
|
16
|
+
|
|
17
|
+
const mockReport = jest.fn();
|
|
18
|
+
let mockValidOptions: boolean;
|
|
19
|
+
|
|
20
|
+
/*
|
|
21
|
+
* The rule reads stylelint's utilities when it loads, so it's required after the mocks they
|
|
22
|
+
* reference are initialized. A static import would be hoisted above them.
|
|
23
|
+
*/
|
|
24
|
+
const { rule } = require('../function-url-no-absolute');
|
|
25
|
+
|
|
26
|
+
describe(`[stylelint-config] ${rule.ruleName} rule`, () => {
|
|
27
|
+
let declaration: string;
|
|
28
|
+
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
jest.clearAllMocks();
|
|
31
|
+
mockValidOptions = true;
|
|
32
|
+
declaration = 'background: url(/assets/image.png)';
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const subject = () => {
|
|
36
|
+
rule(true, {}, {})(postcss.parse(`a { ${declaration} }`), {});
|
|
37
|
+
return mockReport.mock.calls.map(([report]) => report);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
test('reports the absolute url', () => {
|
|
41
|
+
expect(subject()).toEqual([
|
|
42
|
+
expect.objectContaining({
|
|
43
|
+
message: 'Unexpected absolute url',
|
|
44
|
+
index: declaration.indexOf('/assets'),
|
|
45
|
+
endIndex: declaration.indexOf(')'),
|
|
46
|
+
}),
|
|
47
|
+
]);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe.each([
|
|
51
|
+
['double quotes', 'background: url("/assets/image.png")'],
|
|
52
|
+
['single quotes', "background: url('/assets/image.png')"],
|
|
53
|
+
['spaces and quotes', 'background: url( "/assets/image.png" )'],
|
|
54
|
+
['an uppercase function name', 'background: URL(/assets/image.png)'],
|
|
55
|
+
])('with %s', (_description, value) => {
|
|
56
|
+
beforeEach(() => (declaration = value));
|
|
57
|
+
|
|
58
|
+
test('reports the absolute url', () => {
|
|
59
|
+
expect(subject()).toHaveLength(1);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
describe.each([
|
|
64
|
+
['a relative url', 'background: url(./assets/image.png)'],
|
|
65
|
+
['a protocol-relative url', 'background: url(//cdn.example.com/image.png)'],
|
|
66
|
+
['a full url', 'background: url(https://cdn.example.com/image.png)'],
|
|
67
|
+
['a data url', 'background: url(data:image/png;base64,AAAA)'],
|
|
68
|
+
['no url', 'color: red'],
|
|
69
|
+
])('with %s', (_description, value) => {
|
|
70
|
+
beforeEach(() => (declaration = value));
|
|
71
|
+
|
|
72
|
+
test('reports nothing', () => {
|
|
73
|
+
expect(subject()).toEqual([]);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe('with invalid options', () => {
|
|
78
|
+
beforeEach(() => (mockValidOptions = false));
|
|
79
|
+
|
|
80
|
+
test('reports nothing', () => {
|
|
81
|
+
expect(subject()).toEqual([]);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import trim from 'lodash/trim';
|
|
2
1
|
import { Rule, createPlugin, utils } from 'stylelint';
|
|
3
2
|
|
|
4
3
|
const functionArgumentsSearch = (
|
|
@@ -28,7 +27,7 @@ const plugin: Rule = actual => {
|
|
|
28
27
|
|
|
29
28
|
root.walkDecls(decl => {
|
|
30
29
|
functionArgumentsSearch(decl.toString().toLowerCase(), 'url', (args, index) => {
|
|
31
|
-
const url =
|
|
30
|
+
const url = args.replace(/(^[ '"]+)|([ '"]+$)/g, '');
|
|
32
31
|
|
|
33
32
|
if (!isAbsoluteUrl(url)) {
|
|
34
33
|
return;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { fs, vol } from 'memfs';
|
|
2
|
+
import type { Token } from '../load-tokens';
|
|
3
|
+
|
|
4
|
+
jest.mock('fs', () => fs);
|
|
5
|
+
jest.mock('@servicetitan/tokens/core', () => ({
|
|
6
|
+
tokens: mockInstalled(mockDesignSystemTokens),
|
|
7
|
+
}));
|
|
8
|
+
jest.mock('@servicetitan/anvil2/token', () => {
|
|
9
|
+
if (mockAnvil2Error) {
|
|
10
|
+
throw mockAnvil2Error;
|
|
11
|
+
}
|
|
12
|
+
return { core: { primitive: mockInstalled(mockAnvil2Primitives) } };
|
|
13
|
+
});
|
|
14
|
+
jest.mock('@servicetitan/anvil2/package.json', () => {
|
|
15
|
+
if (mockAnvil2Version === undefined) {
|
|
16
|
+
throw Object.assign(new Error('Package subpath not exported'), {
|
|
17
|
+
code: 'ERR_PACKAGE_PATH_NOT_EXPORTED',
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
return { version: mockAnvil2Version };
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
let mockDesignSystemTokens: Record<string, string> | undefined;
|
|
24
|
+
let mockAnvil2Primitives: Record<string, { value: string }> | undefined;
|
|
25
|
+
let mockAnvil2Error: Error | undefined;
|
|
26
|
+
let mockAnvil2Version: string | undefined;
|
|
27
|
+
|
|
28
|
+
function mockInstalled<T>(exports: T | undefined) {
|
|
29
|
+
if (!exports) {
|
|
30
|
+
throw Object.assign(new Error('Cannot find module'), { code: 'MODULE_NOT_FOUND' });
|
|
31
|
+
}
|
|
32
|
+
return exports;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
describe('[stylelint-config] loadTokens', () => {
|
|
36
|
+
const designSystemLessPath = require.resolve('@servicetitan/tokens/core/tokens.less');
|
|
37
|
+
const value = '#0265dc';
|
|
38
|
+
|
|
39
|
+
beforeEach(() => {
|
|
40
|
+
jest.resetModules();
|
|
41
|
+
mockDesignSystemTokens = undefined;
|
|
42
|
+
mockAnvil2Primitives = undefined;
|
|
43
|
+
mockAnvil2Error = undefined;
|
|
44
|
+
mockAnvil2Version = '3.15.0';
|
|
45
|
+
vol.reset();
|
|
46
|
+
vol.fromJSON({ [designSystemLessPath]: '' });
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const subject = (): Token[] => require('../load-tokens').loadTokens();
|
|
50
|
+
|
|
51
|
+
function itReturnsNoTokens() {
|
|
52
|
+
test('returns no tokens', () => {
|
|
53
|
+
expect(subject()).toEqual([]);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
itReturnsNoTokens();
|
|
58
|
+
|
|
59
|
+
describe('with @servicetitan/tokens', () => {
|
|
60
|
+
beforeEach(() => (mockDesignSystemTokens = { colorBlue500: value }));
|
|
61
|
+
|
|
62
|
+
test('returns its tokens', () => {
|
|
63
|
+
expect(subject()).toEqual([
|
|
64
|
+
{
|
|
65
|
+
name: 'color-blue-500',
|
|
66
|
+
customProperty: '--color-blue-500',
|
|
67
|
+
source: '@servicetitan/tokens',
|
|
68
|
+
value,
|
|
69
|
+
},
|
|
70
|
+
]);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe('with an alias', () => {
|
|
74
|
+
beforeEach(() => {
|
|
75
|
+
mockDesignSystemTokens!.colorPrimary = value;
|
|
76
|
+
vol.fromJSON({
|
|
77
|
+
[designSystemLessPath]: '@color-primary: @color-blue-500; // (alias)',
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test('excludes the alias', () => {
|
|
82
|
+
expect(subject().map(({ name }) => name)).toEqual(['color-blue-500']);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
describe('with @servicetitan/anvil2', () => {
|
|
88
|
+
beforeEach(() => (mockAnvil2Primitives = { ColorBlue600: { value } }));
|
|
89
|
+
|
|
90
|
+
test('returns its primitive tokens', () => {
|
|
91
|
+
expect(subject()).toEqual([
|
|
92
|
+
{
|
|
93
|
+
name: 'color-blue-600',
|
|
94
|
+
customProperty: '--a2-color-blue-600',
|
|
95
|
+
source: '@servicetitan/anvil2',
|
|
96
|
+
value,
|
|
97
|
+
},
|
|
98
|
+
]);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
describe('when version is earlier than 3', () => {
|
|
102
|
+
beforeEach(() => (mockAnvil2Version = '2.9.6'));
|
|
103
|
+
|
|
104
|
+
test('omits the "a2" prefix', () => {
|
|
105
|
+
expect(subject()[0].customProperty).toBe('--color-blue-600');
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
describe('when version cannot be determined', () => {
|
|
110
|
+
beforeEach(() => (mockAnvil2Version = undefined));
|
|
111
|
+
|
|
112
|
+
test('adds the "a2" prefix', () => {
|
|
113
|
+
expect(subject()[0].customProperty).toBe('--a2-color-blue-600');
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
describe('without the token export', () => {
|
|
118
|
+
beforeEach(() => {
|
|
119
|
+
mockAnvil2Error = Object.assign(new Error('Package subpath not exported'), {
|
|
120
|
+
code: 'ERR_PACKAGE_PATH_NOT_EXPORTED',
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
itReturnsNoTokens();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
describe('when the package fails to load', () => {
|
|
128
|
+
beforeEach(() => (mockAnvil2Error = new Error('Unexpected token')));
|
|
129
|
+
|
|
130
|
+
test('throws the error', () => {
|
|
131
|
+
expect(subject).toThrow(mockAnvil2Error);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
});
|