@master/css-compiler 2.0.0-rc.71 → 2.0.0-rc.73

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/core.mjs CHANGED
@@ -367,10 +367,136 @@ function formatDeclarationValue(declaration) {
367
367
  throw error;
368
368
  }
369
369
  const colonIndex = declarationText.indexOf(':');
370
- return declarationText.slice(colonIndex + 1).trim();
370
+ return formatCSSNumberLiterals(declarationText.slice(colonIndex + 1).trim());
371
+ }
372
+ function normalizeNumberText(value) {
373
+ const [rawMantissa, rawExponent] = value.toLowerCase().replace('e+', 'e').split('e');
374
+ let mantissa = rawMantissa.replace(/^\+/, '');
375
+ if (mantissa.includes('.')) {
376
+ mantissa = mantissa.replace(/(\.\d*?)0+$/, '$1').replace(/\.$/, '');
377
+ }
378
+ if (mantissa === '-0') mantissa = '0';
379
+ mantissa = mantissa.replace(/^(-?)0\./, '$1.');
380
+ return rawExponent === undefined ? mantissa : `${mantissa}e${rawExponent}`;
371
381
  }
372
382
  function formatNumber(value) {
373
- return String(value).replace(/^(-?)0\./, '$1.');
383
+ if (Object.is(value, -0)) return '0';
384
+ if (!Number.isFinite(value)) return String(value);
385
+ const direct = normalizeNumberText(String(value));
386
+ if (Number.isInteger(value)) return direct;
387
+ const target = Math.fround(value);
388
+ if (!Number.isFinite(target)) return direct;
389
+ let best = direct;
390
+ for(let precision = 1; precision <= 9; precision++){
391
+ const candidate = normalizeNumberText(target.toPrecision(precision));
392
+ if (!Object.is(Math.fround(Number(candidate)), target)) continue;
393
+ if (candidate.length < best.length || candidate.length === best.length && best.includes('e') && !candidate.includes('e')) {
394
+ best = candidate;
395
+ }
396
+ }
397
+ return best;
398
+ }
399
+ function isCSSIdentifierChar(value) {
400
+ return value !== undefined && /[-_a-zA-Z0-9]/.test(value);
401
+ }
402
+ function isCSSDigit(value) {
403
+ return value !== undefined && value >= '0' && value <= '9';
404
+ }
405
+ function canStartCSSNumber(value, index) {
406
+ const previous = value[index - 1];
407
+ if (isCSSIdentifierChar(previous) || previous === '#' || previous === '\\') return false;
408
+ const current = value[index];
409
+ const next = value[index + 1];
410
+ if (current === '+' || current === '-') {
411
+ return isCSSDigit(next) || next === '.' && isCSSDigit(value[index + 2]);
412
+ }
413
+ return isCSSDigit(current) || current === '.' && isCSSDigit(next);
414
+ }
415
+ function readCSSNumber(value, start) {
416
+ let index = start;
417
+ if (value[index] === '+' || value[index] === '-') index++;
418
+ let hasDigits = false;
419
+ while(isCSSDigit(value[index])){
420
+ hasDigits = true;
421
+ index++;
422
+ }
423
+ if (value[index] === '.') {
424
+ index++;
425
+ while(isCSSDigit(value[index])){
426
+ hasDigits = true;
427
+ index++;
428
+ }
429
+ }
430
+ if (!hasDigits) return;
431
+ if (value[index] === 'e' || value[index] === 'E') {
432
+ let exponentIndex = index + 1;
433
+ if (value[exponentIndex] === '+' || value[exponentIndex] === '-') exponentIndex++;
434
+ const exponentStart = exponentIndex;
435
+ while(isCSSDigit(value[exponentIndex]))exponentIndex++;
436
+ if (exponentIndex > exponentStart) index = exponentIndex;
437
+ }
438
+ return {
439
+ text: value.slice(start, index),
440
+ end: index
441
+ };
442
+ }
443
+ function findCSSFunctionEnd(value, start) {
444
+ let depth = 0;
445
+ for(let index = start; index < value.length; index++){
446
+ const char = value[index];
447
+ if (char === '\\') {
448
+ index++;
449
+ continue;
450
+ }
451
+ if (char === '"' || char === '\'') {
452
+ index = findCSSClosingQuote(value, index, char);
453
+ continue;
454
+ }
455
+ if (char === '(') {
456
+ depth++;
457
+ continue;
458
+ }
459
+ if (char === ')') {
460
+ depth--;
461
+ if (depth === 0) return index + 1;
462
+ }
463
+ }
464
+ return value.length;
465
+ }
466
+ function formatCSSNumberLiterals(value) {
467
+ let result = '';
468
+ let index = 0;
469
+ while(index < value.length){
470
+ const char = value[index];
471
+ if (char === '\\') {
472
+ result += value.slice(index, index + 2);
473
+ index += 2;
474
+ continue;
475
+ }
476
+ if (char === '"' || char === '\'') {
477
+ const end = findCSSClosingQuote(value, index, char) + 1;
478
+ result += value.slice(index, end);
479
+ index = end;
480
+ continue;
481
+ }
482
+ if (value.slice(index, index + 4).toLowerCase() === 'url(' && !isCSSIdentifierChar(value[index - 1])) {
483
+ const end = findCSSFunctionEnd(value, index);
484
+ result += value.slice(index, end);
485
+ index = end;
486
+ continue;
487
+ }
488
+ if (canStartCSSNumber(value, index)) {
489
+ const number = readCSSNumber(value, index);
490
+ if (number) {
491
+ result += formatNumber(Number(number.text));
492
+ index = number.end;
493
+ continue;
494
+ }
495
+ }
496
+ result += char;
497
+ index++;
498
+ }
499
+ return result;
374
500
  }
375
501
  function formatDeclarationValueOverride(declaration) {
376
502
  if (declaration.property !== 'aspect-ratio') return;
@@ -443,11 +569,11 @@ function formatToken(token) {
443
569
  case 'unquoted-url':
444
570
  return `url(${token.value})`;
445
571
  case 'number':
446
- return String(token.value);
572
+ return formatNumber(token.value);
447
573
  case 'percentage':
448
- return `${token.value * 100}%`;
574
+ return `${formatNumber(token.value * 100)}%`;
449
575
  case 'dimension':
450
- return `${token.value}${token.unit}`;
576
+ return `${formatNumber(token.value)}${token.unit}`;
451
577
  case 'white-space':
452
578
  return token.value;
453
579
  case 'comment':
@@ -526,12 +652,13 @@ const COMPARISON_OPERATORS = {
526
652
  };
527
653
  function formatFeatureValue(value) {
528
654
  if (value === undefined || value === null) return '';
529
- if (typeof value === 'string' || typeof value === 'number') return String(value);
655
+ if (typeof value === 'string') return value;
656
+ if (typeof value === 'number') return formatNumber(value);
530
657
  switch(value.type){
531
658
  case 'ident':
532
659
  return value.value;
533
660
  case 'number':
534
- return String(value.value);
661
+ return formatNumber(value.value);
535
662
  case 'length':
536
663
  {
537
664
  let resolvedValue = value.value;
@@ -544,7 +671,7 @@ function formatFeatureValue(value) {
544
671
  case 'ratio':
545
672
  return `${value.value.numerator}/${value.value.denominator}`;
546
673
  default:
547
- return formatPrelude(value) || String(value.value ?? '');
674
+ return formatPrelude(value) || (typeof value.value === 'number' ? formatNumber(value.value) : String(value.value ?? ''));
548
675
  }
549
676
  }
550
677
  function formatCondition(condition) {
@@ -1316,9 +1443,9 @@ function formatKeyframeSelector(selector) {
1316
1443
  case 'to':
1317
1444
  return selector.type;
1318
1445
  case 'percentage':
1319
- return `${selector.value * 100}%`;
1446
+ return `${formatNumber(selector.value * 100)}%`;
1320
1447
  case 'timeline-range-percentage':
1321
- return `${selector.value.name} ${selector.value.percentage * 100}%`;
1448
+ return `${selector.value.name} ${formatNumber(selector.value.percentage * 100)}%`;
1322
1449
  }
1323
1450
  }
1324
1451
  function parseKeyframes(rule, manifestInput, isStatic) {
package/dist/index.mjs CHANGED
@@ -3,6 +3,7 @@ import { createRequire } from 'node:module';
3
3
  import { isAbsolute, resolve, extname, dirname } from 'node:path';
4
4
  import { transform } from 'lightningcss';
5
5
  import { stringifyMasterCSSManifestJSON } from '@master/css-schema/manifest-json';
6
+ import { MASTER_CSS_ENTRY_DIRECTIVE_NAME } from '@master/css-lexer';
6
7
  import { createMasterCSSManifest } from './master-css-manifest.mjs';
7
8
  import lowerCSSDirectives from './lower-css-directives.mjs';
8
9
  import { compileCSS, findCSSReferenceStatements, removeCSSReferenceStatements } from './core.mjs';
@@ -78,7 +79,7 @@ function resolveMasterCSSPackageEntryFile(importSource, fromFile = process.cwd()
78
79
  return styleFile;
79
80
  }
80
81
  function inspectCSS(source) {
81
- const hasMasterEntryDirective = findStandaloneMasterDirectiveStatements(source).some((statement)=>statement.name === '');
82
+ const hasMasterEntryDirective = findStandaloneMasterDirectiveStatements(source).some((statement)=>statement.name === MASTER_CSS_ENTRY_DIRECTIVE_NAME);
82
83
  const hasMasterCSSImport = findCSSImportStatements(source).some((statement)=>statement.source === MASTER_CSS_PACKAGE_ID);
83
84
  return {
84
85
  hasMasterEntryDirective,
@@ -1,4 +1,4 @@
1
- import { removeSourceRanges, escapeRegExp } from '@master/css-lexer';
1
+ import { removeSourceRanges, MASTER_CSS_ENTRY_DIRECTIVE_NAME, escapeRegExp } from '@master/css-lexer';
2
2
  import { findAtRuleStatementEnd } from './source.mjs';
3
3
 
4
4
  const STANDALONE_CSS_DIRECTIVE_NAMES = new Set([
@@ -131,8 +131,8 @@ function parseStandaloneCSSDirectiveStatement(source, start, atRuleName) {
131
131
  if (end === -1) return;
132
132
  const statement = source.slice(start, end);
133
133
  const prelude = statement.replace(new RegExp(`^@${atRuleName}\\b`), '').replace(/;$/, '');
134
- if (atRuleName === 'master' && prelude.trim()) return;
135
- const name = atRuleName === 'master' ? '' : atRuleName;
134
+ const name = atRuleName === 'master' ? MASTER_CSS_ENTRY_DIRECTIVE_NAME : atRuleName;
135
+ if (atRuleName === 'master' && prelude.trim() !== MASTER_CSS_ENTRY_DIRECTIVE_NAME) return;
136
136
  return {
137
137
  start,
138
138
  end,
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@master/css-compiler","type":"module","scripts":{"build":"techor build \"src/**/*.ts\" --formats esm","dev":"pnpm build --watch","lint":"eslint","type-check":"tsc --noEmit","test":"vitest"},"license":"MIT","description":"Compile Master CSS stylesheet directives","author":"Aoyue Design LLC.","funding":"https://rc.css.master.co/sponsor","homepage":"https://css.master.co","bugs":{"url":"https://github.com/master-co/css/issues"},"repository":{"type":"git","url":"https://github.com/master-co/css.git","directory":"packages/compiler"},"keywords":["compiler","directives","css","mastercss"],"sideEffects":false,"main":"./dist/index.mjs","module":"./dist/index.mjs","jsnext:main":"./dist/index.mjs","esnext":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","default":"./dist/index.mjs"},"./browser":{"types":"./dist/browser.d.ts","import":"./dist/browser.mjs","default":"./dist/browser.mjs"}},"files":["dist"],"publishConfig":{"access":"public","provenance":true},"dependencies":{"@master/css-engine":"^2.0.0-rc.71","@master/css-lexer":"^2.0.0-rc.71","css-tree":"^3.2.1","csstype":"^3.2.3","lightningcss":"^1.32.0","lightningcss-wasm":"^1.32.0","@master/css-schema":"^2.0.0-rc.71"},"devDependencies":{"@master/css-preset":"^2.0.0-rc.71","@types/css-tree":"^2.3.11"},"version":"2.0.0-rc.71"}
1
+ {"name":"@master/css-compiler","type":"module","scripts":{"build":"techor build \"src/**/*.ts\" --formats esm","dev":"pnpm build --watch","lint":"eslint","type-check":"tsc --noEmit","test":"vitest"},"license":"MIT","description":"Compile Master CSS stylesheet directives","author":"Aoyue Design LLC.","funding":"https://rc.css.master.co/sponsor","homepage":"https://css.master.co","bugs":{"url":"https://github.com/master-co/css/issues"},"repository":{"type":"git","url":"https://github.com/master-co/css.git","directory":"packages/compiler"},"keywords":["compiler","directives","css","mastercss"],"sideEffects":false,"main":"./dist/index.mjs","module":"./dist/index.mjs","jsnext:main":"./dist/index.mjs","esnext":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","default":"./dist/index.mjs"},"./browser":{"types":"./dist/browser.d.ts","import":"./dist/browser.mjs","default":"./dist/browser.mjs"}},"files":["dist"],"publishConfig":{"access":"public","provenance":true},"dependencies":{"@master/css-engine":"^2.0.0-rc.73","@master/css-lexer":"^2.0.0-rc.73","css-tree":"^3.2.1","csstype":"^3.2.3","lightningcss":"^1.32.0","lightningcss-wasm":"^1.32.0","@master/css-schema":"^2.0.0-rc.73"},"devDependencies":{"@master/css-preset":"^2.0.0-rc.73","@types/css-tree":"^2.3.11"},"version":"2.0.0-rc.73"}