@ripple-ts/prettier-plugin 0.2.169 → 0.2.171
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/package.json +2 -2
- package/src/index.js +74 -284
- package/src/index.test.js +80 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ripple-ts/prettier-plugin",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.171",
|
|
4
4
|
"description": "Ripple plugin for Prettier",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "src/index.js",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"prettier": "^3.6.2",
|
|
28
|
-
"ripple": "0.2.
|
|
28
|
+
"ripple": "0.2.171"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {},
|
|
31
31
|
"files": [
|
package/src/index.js
CHANGED
|
@@ -21,11 +21,6 @@ const {
|
|
|
21
21
|
} = builders;
|
|
22
22
|
const { willBreak } = utils;
|
|
23
23
|
|
|
24
|
-
// Embed function - not needed for now
|
|
25
|
-
export function embed(path, options) {
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
24
|
export const languages = [
|
|
30
25
|
{
|
|
31
26
|
name: 'ripple',
|
|
@@ -39,8 +34,7 @@ export const parsers = {
|
|
|
39
34
|
ripple: {
|
|
40
35
|
astFormat: 'ripple-ast',
|
|
41
36
|
parse(text, parsers, options) {
|
|
42
|
-
|
|
43
|
-
return ast;
|
|
37
|
+
return parse(text);
|
|
44
38
|
},
|
|
45
39
|
|
|
46
40
|
locStart(node) {
|
|
@@ -66,11 +60,50 @@ export const printers = {
|
|
|
66
60
|
}
|
|
67
61
|
return typeof parts === 'string' ? parts : parts;
|
|
68
62
|
},
|
|
63
|
+
embed(path, options) {
|
|
64
|
+
const node = path.getValue();
|
|
65
|
+
|
|
66
|
+
// Handle StyleSheet nodes inside style tags
|
|
67
|
+
if (node.type === 'StyleSheet' && node.source) {
|
|
68
|
+
// Return async function that will be called by Prettier
|
|
69
|
+
return async (textToDoc) => {
|
|
70
|
+
try {
|
|
71
|
+
// Format CSS using Prettier's textToDoc
|
|
72
|
+
const body = await textToDoc(node.source, {
|
|
73
|
+
parser: 'css',
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Return the formatted CSS
|
|
77
|
+
// Note: printElement will wrap this in indent(), so we don't add indent here
|
|
78
|
+
return body;
|
|
79
|
+
} catch (error) {
|
|
80
|
+
// If CSS has syntax errors, return original unformatted content
|
|
81
|
+
console.error('Error formatting CSS:', error);
|
|
82
|
+
return node.source;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return null;
|
|
88
|
+
},
|
|
69
89
|
getVisitorKeys(node) {
|
|
90
|
+
// Exclude metadata and raw text properties that shouldn't be traversed
|
|
91
|
+
// The css property is specifically excluded so embed() can handle it
|
|
92
|
+
const excludedKeys = new Set([
|
|
93
|
+
'start',
|
|
94
|
+
'end',
|
|
95
|
+
'loc',
|
|
96
|
+
'metadata',
|
|
97
|
+
'css', // Handled by embed()
|
|
98
|
+
'raw',
|
|
99
|
+
'regex',
|
|
100
|
+
]);
|
|
101
|
+
|
|
70
102
|
const keys = Object.keys(node).filter((key) => {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
103
|
+
if (excludedKeys.has(key)) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
return typeof node[key] === 'object' && node[key] !== null;
|
|
74
107
|
});
|
|
75
108
|
|
|
76
109
|
return keys;
|
|
@@ -1923,61 +1956,6 @@ function printRippleNode(node, path, options, print, args) {
|
|
|
1923
1956
|
}
|
|
1924
1957
|
break;
|
|
1925
1958
|
|
|
1926
|
-
case 'StyleSheet':
|
|
1927
|
-
nodeContent = printStyleSheet(node, path, options, print);
|
|
1928
|
-
break;
|
|
1929
|
-
case 'Rule':
|
|
1930
|
-
nodeContent = printCSSRule(node, path, options, print);
|
|
1931
|
-
break;
|
|
1932
|
-
|
|
1933
|
-
case 'Declaration':
|
|
1934
|
-
nodeContent = printCSSDeclaration(node, path, options, print);
|
|
1935
|
-
break;
|
|
1936
|
-
|
|
1937
|
-
case 'Atrule':
|
|
1938
|
-
nodeContent = printCSSAtrule(node, path, options, print);
|
|
1939
|
-
break;
|
|
1940
|
-
|
|
1941
|
-
case 'SelectorList':
|
|
1942
|
-
nodeContent = printCSSSelectorList(node, path, options, print);
|
|
1943
|
-
break;
|
|
1944
|
-
|
|
1945
|
-
case 'ComplexSelector':
|
|
1946
|
-
nodeContent = printCSSComplexSelector(node, path, options, print);
|
|
1947
|
-
break;
|
|
1948
|
-
|
|
1949
|
-
case 'RelativeSelector':
|
|
1950
|
-
nodeContent = printCSSRelativeSelector(node, path, options, print);
|
|
1951
|
-
break;
|
|
1952
|
-
|
|
1953
|
-
case 'TypeSelector':
|
|
1954
|
-
nodeContent = printCSSTypeSelector(node, path, options, print);
|
|
1955
|
-
break;
|
|
1956
|
-
|
|
1957
|
-
case 'IdSelector':
|
|
1958
|
-
nodeContent = printCSSIdSelector(node, path, options, print);
|
|
1959
|
-
break;
|
|
1960
|
-
|
|
1961
|
-
case 'ClassSelector':
|
|
1962
|
-
nodeContent = printCSSClassSelector(node, path, options, print);
|
|
1963
|
-
break;
|
|
1964
|
-
|
|
1965
|
-
case 'NestingSelector':
|
|
1966
|
-
nodeContent = printCSSNestingSelector(node, path, options, print);
|
|
1967
|
-
break;
|
|
1968
|
-
|
|
1969
|
-
case 'PseudoClassSelector':
|
|
1970
|
-
nodeContent = printCSSPseudoClassSelector(node, path, options, print);
|
|
1971
|
-
break;
|
|
1972
|
-
|
|
1973
|
-
case 'PseudoElementSelector':
|
|
1974
|
-
nodeContent = printCSSPseudoElementSelector(node, path, options, print);
|
|
1975
|
-
break;
|
|
1976
|
-
|
|
1977
|
-
case 'Block':
|
|
1978
|
-
nodeContent = printCSSBlock(node, path, options, print);
|
|
1979
|
-
break;
|
|
1980
|
-
|
|
1981
1959
|
case 'Attribute':
|
|
1982
1960
|
nodeContent = printAttribute(node, path, options, print);
|
|
1983
1961
|
break;
|
|
@@ -2066,7 +2044,6 @@ function printRippleNode(node, path, options, print, args) {
|
|
|
2066
2044
|
}
|
|
2067
2045
|
|
|
2068
2046
|
function printImportDeclaration(node, path, options, print) {
|
|
2069
|
-
// Use Prettier's doc builders for proper cursor tracking
|
|
2070
2047
|
const parts = ['import'];
|
|
2071
2048
|
|
|
2072
2049
|
// Handle type imports
|
|
@@ -2095,25 +2072,47 @@ function printImportDeclaration(node, path, options, print) {
|
|
|
2095
2072
|
}
|
|
2096
2073
|
});
|
|
2097
2074
|
|
|
2098
|
-
// Build import clause
|
|
2099
|
-
const
|
|
2075
|
+
// Build import clause with proper grouping and line breaking
|
|
2076
|
+
const importClauseParts = [];
|
|
2077
|
+
|
|
2100
2078
|
if (defaultImports.length > 0) {
|
|
2101
|
-
|
|
2079
|
+
importClauseParts.push(defaultImports.join(', '));
|
|
2102
2080
|
}
|
|
2103
2081
|
if (namespaceImports.length > 0) {
|
|
2104
|
-
|
|
2082
|
+
importClauseParts.push(namespaceImports.join(', '));
|
|
2105
2083
|
}
|
|
2106
2084
|
if (namedImports.length > 0) {
|
|
2107
|
-
|
|
2085
|
+
// Use Prettier's group and conditionalGroup for named imports to handle line breaking
|
|
2086
|
+
const namedImportsDocs = namedImports.map((name) => name);
|
|
2087
|
+
const namedImportsGroup = group(
|
|
2088
|
+
concat([
|
|
2089
|
+
'{',
|
|
2090
|
+
indent(
|
|
2091
|
+
concat([
|
|
2092
|
+
options.bracketSpacing ? line : softline,
|
|
2093
|
+
join(concat([',', line]), namedImportsDocs),
|
|
2094
|
+
]),
|
|
2095
|
+
),
|
|
2096
|
+
ifBreak(shouldPrintComma(options) ? ',' : ''),
|
|
2097
|
+
options.bracketSpacing ? line : softline,
|
|
2098
|
+
'}',
|
|
2099
|
+
]),
|
|
2100
|
+
);
|
|
2101
|
+
importClauseParts.push(namedImportsGroup);
|
|
2108
2102
|
}
|
|
2109
2103
|
|
|
2110
|
-
parts.push(' '
|
|
2104
|
+
parts.push(' ');
|
|
2105
|
+
if (importClauseParts.length === 1 && typeof importClauseParts[0] === 'object') {
|
|
2106
|
+
parts.push(importClauseParts[0]);
|
|
2107
|
+
} else {
|
|
2108
|
+
parts.push(join(', ', importClauseParts));
|
|
2109
|
+
}
|
|
2110
|
+
parts.push(' from');
|
|
2111
2111
|
}
|
|
2112
2112
|
|
|
2113
|
-
parts.push(' '
|
|
2113
|
+
parts.push(' ', formatStringLiteral(node.source.value, options), semi(options));
|
|
2114
2114
|
|
|
2115
|
-
|
|
2116
|
-
return parts;
|
|
2115
|
+
return concat(parts);
|
|
2117
2116
|
}
|
|
2118
2117
|
|
|
2119
2118
|
function printExportNamedDeclaration(node, path, options, print) {
|
|
@@ -4319,215 +4318,6 @@ function printTSIndexedAccessType(node, path, options, print) {
|
|
|
4319
4318
|
return concat([path.call(print, 'objectType'), '[', path.call(print, 'indexType'), ']']);
|
|
4320
4319
|
}
|
|
4321
4320
|
|
|
4322
|
-
function printStyleSheet(node, path, options, print) {
|
|
4323
|
-
// StyleSheet contains CSS rules in the 'body' property
|
|
4324
|
-
if (node.body && node.body.length > 0) {
|
|
4325
|
-
const cssItems = [];
|
|
4326
|
-
|
|
4327
|
-
// Process each item in the stylesheet body
|
|
4328
|
-
for (let i = 0; i < node.body.length; i++) {
|
|
4329
|
-
const item = path.call(print, 'body', i);
|
|
4330
|
-
if (item) {
|
|
4331
|
-
cssItems.push(item);
|
|
4332
|
-
}
|
|
4333
|
-
}
|
|
4334
|
-
|
|
4335
|
-
// Structure the CSS with proper indentation and spacing
|
|
4336
|
-
// Check for blank lines between CSS items and preserve them
|
|
4337
|
-
const result = [];
|
|
4338
|
-
for (let i = 0; i < cssItems.length; i++) {
|
|
4339
|
-
result.push(cssItems[i]);
|
|
4340
|
-
if (i < cssItems.length - 1) {
|
|
4341
|
-
// Check if there are blank lines between current and next item
|
|
4342
|
-
const currentItem = node.body[i];
|
|
4343
|
-
const nextItem = node.body[i + 1];
|
|
4344
|
-
|
|
4345
|
-
// Check for blank lines in the original CSS source between rules
|
|
4346
|
-
let hasBlankLine = false;
|
|
4347
|
-
if (
|
|
4348
|
-
node.source &&
|
|
4349
|
-
typeof currentItem.end === 'number' &&
|
|
4350
|
-
typeof nextItem.start === 'number'
|
|
4351
|
-
) {
|
|
4352
|
-
const textBetween = node.source.substring(currentItem.end, nextItem.start);
|
|
4353
|
-
// Count newlines in the text between the rules
|
|
4354
|
-
const newlineCount = (textBetween.match(/\n/g) || []).length;
|
|
4355
|
-
// If there are 2 or more newlines, there's at least one blank line
|
|
4356
|
-
hasBlankLine = newlineCount >= 2;
|
|
4357
|
-
}
|
|
4358
|
-
if (hasBlankLine) {
|
|
4359
|
-
// If there are blank lines, add an extra hardline (to create a blank line)
|
|
4360
|
-
result.push(hardline, hardline);
|
|
4361
|
-
} else {
|
|
4362
|
-
result.push(hardline);
|
|
4363
|
-
}
|
|
4364
|
-
}
|
|
4365
|
-
}
|
|
4366
|
-
|
|
4367
|
-
return concat(result);
|
|
4368
|
-
}
|
|
4369
|
-
|
|
4370
|
-
// If no body, return empty string
|
|
4371
|
-
return '';
|
|
4372
|
-
}
|
|
4373
|
-
|
|
4374
|
-
function printCSSRule(node, path, options, print) {
|
|
4375
|
-
// CSS Rule has prelude (selector) and block (declarations)
|
|
4376
|
-
const selector = path.call(print, 'prelude');
|
|
4377
|
-
const block = path.call(print, 'block');
|
|
4378
|
-
|
|
4379
|
-
return group([selector, ' {', indent([hardline, block]), hardline, '}']);
|
|
4380
|
-
}
|
|
4381
|
-
|
|
4382
|
-
function printCSSDeclaration(node, path, options, print) {
|
|
4383
|
-
// CSS Declaration has property and value
|
|
4384
|
-
const parts = [node.property];
|
|
4385
|
-
|
|
4386
|
-
if (node.value) {
|
|
4387
|
-
parts.push(': ');
|
|
4388
|
-
const value = path.call(print, 'value');
|
|
4389
|
-
parts.push(value);
|
|
4390
|
-
}
|
|
4391
|
-
|
|
4392
|
-
parts.push(';');
|
|
4393
|
-
return concat(parts);
|
|
4394
|
-
}
|
|
4395
|
-
|
|
4396
|
-
function printCSSAtrule(node, path, options, print) {
|
|
4397
|
-
// CSS At-rule like @media, @keyframes, etc.
|
|
4398
|
-
const parts = ['@', node.name];
|
|
4399
|
-
|
|
4400
|
-
if (node.prelude) {
|
|
4401
|
-
parts.push(' ');
|
|
4402
|
-
const prelude = path.call(print, 'prelude');
|
|
4403
|
-
parts.push(prelude);
|
|
4404
|
-
}
|
|
4405
|
-
|
|
4406
|
-
if (node.block) {
|
|
4407
|
-
const block = path.call(print, 'block');
|
|
4408
|
-
parts.push(' {');
|
|
4409
|
-
parts.push(indent([hardline, block]));
|
|
4410
|
-
parts.push(hardline, '}');
|
|
4411
|
-
} else {
|
|
4412
|
-
parts.push(';');
|
|
4413
|
-
}
|
|
4414
|
-
|
|
4415
|
-
return group(parts);
|
|
4416
|
-
}
|
|
4417
|
-
|
|
4418
|
-
function printCSSSelectorList(node, path, options, print) {
|
|
4419
|
-
// SelectorList contains multiple selectors
|
|
4420
|
-
if (node.children && node.children.length > 0) {
|
|
4421
|
-
const selectors = [];
|
|
4422
|
-
for (let i = 0; i < node.children.length; i++) {
|
|
4423
|
-
const selector = path.call(print, 'children', i);
|
|
4424
|
-
selectors.push(selector);
|
|
4425
|
-
}
|
|
4426
|
-
// Join selectors with comma and line break for proper CSS formatting
|
|
4427
|
-
return join([',', hardline], selectors);
|
|
4428
|
-
}
|
|
4429
|
-
return '';
|
|
4430
|
-
}
|
|
4431
|
-
|
|
4432
|
-
function printCSSComplexSelector(node, path, options, print) {
|
|
4433
|
-
// ComplexSelector contains selector components
|
|
4434
|
-
if (node.children && node.children.length > 0) {
|
|
4435
|
-
const selectorParts = [];
|
|
4436
|
-
for (let i = 0; i < node.children.length; i++) {
|
|
4437
|
-
const part = path.call(print, 'children', i);
|
|
4438
|
-
selectorParts.push(part);
|
|
4439
|
-
}
|
|
4440
|
-
return concat(selectorParts);
|
|
4441
|
-
}
|
|
4442
|
-
return '';
|
|
4443
|
-
}
|
|
4444
|
-
|
|
4445
|
-
function printCSSRelativeSelector(node, path, options, print) {
|
|
4446
|
-
// RelativeSelector contains selector components in the 'selectors' property
|
|
4447
|
-
const parts = [];
|
|
4448
|
-
|
|
4449
|
-
// Print combinator if it exists (e.g., +, >, ~, or space)
|
|
4450
|
-
if (node.combinator) {
|
|
4451
|
-
if (node.combinator.name === ' ') {
|
|
4452
|
-
// Space combinator (descendant selector)
|
|
4453
|
-
parts.push(' ');
|
|
4454
|
-
} else {
|
|
4455
|
-
// Other combinators (+, >, ~)
|
|
4456
|
-
parts.push(' ', node.combinator.name, ' ');
|
|
4457
|
-
}
|
|
4458
|
-
}
|
|
4459
|
-
|
|
4460
|
-
if (node.selectors && node.selectors.length > 0) {
|
|
4461
|
-
const selectorParts = [];
|
|
4462
|
-
for (let i = 0; i < node.selectors.length; i++) {
|
|
4463
|
-
const part = path.call(print, 'selectors', i);
|
|
4464
|
-
selectorParts.push(part);
|
|
4465
|
-
}
|
|
4466
|
-
parts.push(...selectorParts);
|
|
4467
|
-
}
|
|
4468
|
-
|
|
4469
|
-
return concat(parts);
|
|
4470
|
-
}
|
|
4471
|
-
|
|
4472
|
-
function printCSSTypeSelector(node, path, options, print) {
|
|
4473
|
-
// TypeSelector for element names like 'div', 'body', 'p', etc.
|
|
4474
|
-
return node.name || '';
|
|
4475
|
-
}
|
|
4476
|
-
|
|
4477
|
-
function printCSSIdSelector(node, path, options, print) {
|
|
4478
|
-
// IdSelector for #id
|
|
4479
|
-
return concat(['#', node.name || '']);
|
|
4480
|
-
}
|
|
4481
|
-
|
|
4482
|
-
function printCSSClassSelector(node, path, options, print) {
|
|
4483
|
-
// ClassSelector for .class
|
|
4484
|
-
return concat(['.', node.name || '']);
|
|
4485
|
-
}
|
|
4486
|
-
|
|
4487
|
-
function printCSSNestingSelector(node, path, options, print) {
|
|
4488
|
-
// NestingSelector for & (parent reference in nested CSS)
|
|
4489
|
-
return '&';
|
|
4490
|
-
}
|
|
4491
|
-
|
|
4492
|
-
function printCSSPseudoClassSelector(node, path, options, print) {
|
|
4493
|
-
// PseudoClassSelector for :hover, :global(), etc.
|
|
4494
|
-
const parts = [':', node.name || ''];
|
|
4495
|
-
|
|
4496
|
-
// If it has args (like :global(.classname)), print them
|
|
4497
|
-
if (node.args !== null && node.args !== undefined) {
|
|
4498
|
-
parts.push('(', node.args, ')');
|
|
4499
|
-
}
|
|
4500
|
-
|
|
4501
|
-
return concat(parts);
|
|
4502
|
-
}
|
|
4503
|
-
|
|
4504
|
-
function printCSSPseudoElementSelector(node, path, options, print) {
|
|
4505
|
-
// PseudoElementSelector for ::before, ::after, etc.
|
|
4506
|
-
const parts = ['::', node.name || ''];
|
|
4507
|
-
|
|
4508
|
-
// If it has args (like ::slotted(span)), print them
|
|
4509
|
-
if (node.args !== null && node.args !== undefined) {
|
|
4510
|
-
parts.push('(', node.args, ')');
|
|
4511
|
-
}
|
|
4512
|
-
|
|
4513
|
-
return concat(parts);
|
|
4514
|
-
}
|
|
4515
|
-
|
|
4516
|
-
function printCSSBlock(node, path, options, print) {
|
|
4517
|
-
// CSS Block contains declarations
|
|
4518
|
-
if (node.children && node.children.length > 0) {
|
|
4519
|
-
const declarations = [];
|
|
4520
|
-
for (let i = 0; i < node.children.length; i++) {
|
|
4521
|
-
const decl = path.call(print, 'children', i);
|
|
4522
|
-
if (decl) {
|
|
4523
|
-
declarations.push(decl);
|
|
4524
|
-
}
|
|
4525
|
-
}
|
|
4526
|
-
return join(hardline, declarations);
|
|
4527
|
-
}
|
|
4528
|
-
return '';
|
|
4529
|
-
}
|
|
4530
|
-
|
|
4531
4321
|
function shouldInlineSingleChild(parentNode, firstChild, childDoc) {
|
|
4532
4322
|
if (!firstChild || childDoc == null) {
|
|
4533
4323
|
return false;
|
package/src/index.test.js
CHANGED
|
@@ -663,6 +663,33 @@ import { Something, type Props, track } from 'ripple';`;
|
|
|
663
663
|
expect(result).toBeWithNewline(expected);
|
|
664
664
|
});
|
|
665
665
|
|
|
666
|
+
it('should format long import statements correctly', async () => {
|
|
667
|
+
const input = `import { flushSync, track, effect, bindValue, bindChecked, bindGroup, bindClientWidth, bindClientHeight, bindOffsetWidth, bindOffsetHeight, bindContentRect, bindContentBoxSize, bindBorderBoxSize, bindDevicePixelContentBoxSize, bindInnerHTML, bindInnerText, bindTextContent, bindNode } from 'ripple';`;
|
|
668
|
+
const expected = `import {
|
|
669
|
+
flushSync,
|
|
670
|
+
track,
|
|
671
|
+
effect,
|
|
672
|
+
bindValue,
|
|
673
|
+
bindChecked,
|
|
674
|
+
bindGroup,
|
|
675
|
+
bindClientWidth,
|
|
676
|
+
bindClientHeight,
|
|
677
|
+
bindOffsetWidth,
|
|
678
|
+
bindOffsetHeight,
|
|
679
|
+
bindContentRect,
|
|
680
|
+
bindContentBoxSize,
|
|
681
|
+
bindBorderBoxSize,
|
|
682
|
+
bindDevicePixelContentBoxSize,
|
|
683
|
+
bindInnerHTML,
|
|
684
|
+
bindInnerText,
|
|
685
|
+
bindTextContent,
|
|
686
|
+
bindNode,
|
|
687
|
+
} from 'ripple';`;
|
|
688
|
+
|
|
689
|
+
const result = await format(input, { singleQuote: true, printWidth: 80 });
|
|
690
|
+
expect(result).toBeWithNewline(expected);
|
|
691
|
+
});
|
|
692
|
+
|
|
666
693
|
it('should preserve @ symbol in JSX attributes and shorthand syntax', async () => {
|
|
667
694
|
const input = `component App() {
|
|
668
695
|
const count = track(0);
|
|
@@ -1135,6 +1162,59 @@ const [obj1, obj2] = arrayOfObjects;`;
|
|
|
1135
1162
|
expect(result).toBeWithNewline(expected);
|
|
1136
1163
|
});
|
|
1137
1164
|
|
|
1165
|
+
it('should keep css @keyframes syntax intact', async () => {
|
|
1166
|
+
const input = `export component App() {
|
|
1167
|
+
<style>
|
|
1168
|
+
/* Scoped keyframe - only usable within Parent */
|
|
1169
|
+
@keyframes slideIn {
|
|
1170
|
+
from { transform: translateX(-100%); }
|
|
1171
|
+
to { transform: translateX(0); }
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
/* Global keyframe - usable in any component */
|
|
1175
|
+
@keyframes -global-fadeIn {
|
|
1176
|
+
0% { opacity: 0; }
|
|
1177
|
+
100% { opacity: 1; }
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
.parent {
|
|
1181
|
+
animation: slideIn 1s;
|
|
1182
|
+
}
|
|
1183
|
+
</style>
|
|
1184
|
+
}`;
|
|
1185
|
+
|
|
1186
|
+
const expected = `export component App() {
|
|
1187
|
+
<style>
|
|
1188
|
+
/* Scoped keyframe - only usable within Parent */
|
|
1189
|
+
@keyframes slideIn {
|
|
1190
|
+
from {
|
|
1191
|
+
transform: translateX(-100%);
|
|
1192
|
+
}
|
|
1193
|
+
to {
|
|
1194
|
+
transform: translateX(0);
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
/* Global keyframe - usable in any component */
|
|
1199
|
+
@keyframes -global-fadeIn {
|
|
1200
|
+
0% {
|
|
1201
|
+
opacity: 0;
|
|
1202
|
+
}
|
|
1203
|
+
100% {
|
|
1204
|
+
opacity: 1;
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
.parent {
|
|
1209
|
+
animation: slideIn 1s;
|
|
1210
|
+
}
|
|
1211
|
+
</style>
|
|
1212
|
+
}`;
|
|
1213
|
+
|
|
1214
|
+
const result = await format(input, { singleQuote: true, printWidth: 100 });
|
|
1215
|
+
expect(result).toBeWithNewline(expected);
|
|
1216
|
+
});
|
|
1217
|
+
|
|
1138
1218
|
it('should keep TrackedMap short syntax intact', async () => {
|
|
1139
1219
|
const expected = `const map = new #Map([['key1', 'value1'], ['key2', 'value2']]);
|
|
1140
1220
|
const set = new #Set([1, 2, 3]);`;
|