fscss 1.1.13 → 1.1.15

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/README.md CHANGED
@@ -1,48 +1,50 @@
1
1
  # FSCSS
2
2
  FSCSS (Figured Shorthand CSS) is a CSS preprocessor that extends CSS with shorthand utilities, variables, functions, and advanced transformations.
3
- It works both in the browser and on the backend (Node.js).
4
3
 
5
4
 
6
5
  ---
7
6
 
8
7
 
9
8
 
10
- ## Features
9
+ ## Features
11
10
 
12
11
  Works in browser and backend (Node.js)
13
12
 
14
13
  Supports:
15
14
 
16
- - Variables ($var, str()) → define reusable values
17
-
18
- - Style Replacement (%n()) → shorthand repeated properties
15
+ - Reusable block@define name(x,y){...} - https://github.com/fscss-ttr/FSCSS/blob/main/FSCSS_%40define_method.md
16
+
17
+ - Variables ($var, str()) → define reusable values, str(boxBased, "..."), $var:...;
18
+
19
+ - Array Methods (@arr) → define array - https://github.com/fscss-ttr/FSCSS/blob/main/FSCSS_array_method.md
20
+
21
+ - Style Replacement (%n()) → shorthand repeated properties. %2(width, height[: 200px;])
22
+
19
23
  - Repeat Function (rpt()) → repeat values quickly
20
24
 
21
25
  - Copy Function (copy()) → copy parts of values
22
26
 
23
- - String Extractor (@ext()) → extract substrings from values
27
+ - String Extractor (@ext()) → extract substrings from values.
24
28
 
25
- - Drops / Shared Properties → reuse style groups
29
+ - Drops / Shared Properties → reuse style groups.
26
30
 
27
- - Attribute Selectors → dynamic selectors
31
+ - Attribute Selectors → dynamic selectors. $(attribute:value){...}
28
32
 
29
33
  - Keyframes ($(@keyframes …)) → generate animations easily
30
34
 
31
- - Vendor Prefixing (-*) → auto add prefixes
32
-
33
- - Function-based (@fun) → reusable function-like blocks
35
+ - Vendor Prefixing (-*) → auto add prefixes. -\*-webkit-text-stroke:...
34
36
 
35
- - Array Methods (@arr) → define & loop arrays
37
+ - Function-based (@fun) → reusable function-like blocks. @fun(name){...}
36
38
 
37
- - Random Function (@random()) → random values at runtime
39
+ - Random Function (@random()) → random values at runtime. @random([.,.,...]) or using array!.randint instead
38
40
 
39
- - Number Calculation (num()) → evaluate math expressions
41
+ - Number Calculation (num()) → evaluate math expressions. num(4+5)
40
42
 
41
- - Import (@import) → include external FSCSS files
43
+ - Import (@import) → include external FSCSS files. @import(exec(...))
42
44
 
43
45
  - @event → event-based styling logic
44
46
 
45
- - exec() → debugging and runtime helpers
47
+ - exec() → debugging and runtime helpers. exec(_log, "...")
46
48
 
47
49
  - Variable fallback chain (property: $/var || fallback;)
48
50
 
@@ -50,7 +52,7 @@ Supports:
50
52
  ### Example
51
53
  ```css
52
54
  /* FSCSS, Animation compact */
53
- $(@keyframes trans, .box .card &[3s ease-in infinite]) {
55
+ $(@keyframes trans, .box, .card &[3s ase-in infinite]) {
54
56
  from {
55
57
  %2(width, height [: 0;])
56
58
  background: red;
@@ -62,7 +64,7 @@ $(@keyframes trans, .box .card &[3s ease-in infinite]) {
62
64
  }
63
65
  ```
64
66
 
65
- ### 📦 Installation
67
+ ### Installation
66
68
 
67
69
  `npm install -g fscss`
68
70
 
@@ -72,7 +74,7 @@ Or locally to your project:
72
74
 
73
75
  **Browser CDN**
74
76
  ```html
75
- <script src="https://cdn.jsdelivr.net/npm/fscss@1.1.13/exec.min.js" defer></script>
77
+ <script src="https://cdn.jsdelivr.net/npm/fscss@1.1.14/exec.min.js" defer></script>
76
78
  ```
77
79
  Usage
78
80
 
@@ -86,7 +88,7 @@ Or import inside a style block:
86
88
  @import(exec(style.fscss))
87
89
  </style>
88
90
  ```
89
- **⚡ Async or defer is required for script loading.**
91
+ **Async or defer is required for script loading.**
90
92
 
91
93
 
92
94
  ---
package/example.fscss CHANGED
@@ -1,7 +1,25 @@
1
1
  @import(exec(_init themes))
2
2
  @import(exec(style.fscss).pick(body))
3
- div{
4
- background: @event.theme(forest);
5
- %2(width, height[: 200px;])
6
- tr Shape: @event.shape(star);
7
- }
3
+ @define card(bg, color: white){
4
+ background: @use(bg);
5
+ color: @use(color);
6
+ padding: 10px;
7
+ border-radius: 10px;
8
+ }
9
+ @arr colors[#1E2783, #8C29B2, #C41348]
10
+ $colors: @arr.colors!;
11
+ div{
12
+ background: @event.theme(forest);
13
+ %2(width, height[: 200px;])
14
+ tr Shape: @event.shape(star);
15
+ }
16
+ .box{
17
+ background: radial-gradient(40deg, $colors.list);
18
+ }
19
+ .box-b{
20
+ background: radial-gradient(40deg, $colors.reverse);
21
+ }
22
+ .card{
23
+ @card(#007999)
24
+ }
25
+ exec(_log, "Hello World!")
@@ -38,10 +38,12 @@ const processedCSS = css.replace(regex, (match, expression) => {
38
38
 
39
39
  return (processedCSS);
40
40
  }
41
- const arraysExfscss = {}; // Renamed the global variable
41
+ const arraysExfscss = {}; //the global variable
42
42
  const orderedxFscssRandom = {};
43
43
 
44
44
  const exfMAX_DEPTH = 10; // Prevent infinite recursion
45
+ const defExfscss = {};
46
+
45
47
  function extractBlock(css, startIndex) {
46
48
  let depth = 0;
47
49
  let i = startIndex;
@@ -260,12 +262,67 @@ function procExC(css) {
260
262
 
261
263
  return modifiedCSS.trim();
262
264
  }
265
+
263
266
  function initlibraries(css){
264
267
  css = css.replace(/exec\(\s*_init\sisjs\s*\)/g, "exec(https://cdn.jsdelivr.net/gh/fscss-ttr/FSCSS@main/xf/styles/isjs.fscss)");
265
268
  css = css.replace(/exec\(\s*_init\sthemes\s*\)/g, "exec(https://cdn.jsdelivr.net/gh/fscss-ttr/FSCSS@main/xf/styles/trshapes.fthemes.fscss)")
266
269
  css = css.replace(/exec\(_init\sarray1to500\s*\)/g, "exec(https://cdn.jsdelivr.net/gh/fscss-ttr/FSCSS@main/xf/styles/1to500.fscss)");
270
+ css = css.replace(/exec\(_init\s+([\w\d\._—\-\%\*\+\&\$\=]+)(?:\/([\w\-]+))?\s*\)/g, (match, impName, impType)=>{
271
+ if(!impType){
272
+ //`
273
+ return `exec(https://cdn.jsdelivr.net/gh/fscss-ttr/FSCSS@main/xf/styles/${impName}.fscss)`;
274
+ }
275
+ return `exec(https://cdn.jsdelivr.net/gh/fscss-ttr/FSCSS@main/xf/styles/${impName}.${impType})`;
276
+ });
267
277
  return css;
268
278
  }
279
+
280
+ function procDef(fscss) {
281
+ // First, extract all @define blocks and store them in defExfscss. FIGSH-FSCSS
282
+ let processed = fscss.replace(
283
+ /@define\s+([\w\_\-\—]+)\s*\(([^)]*)\)\s*\$?\{\s*(?:"([^"]*)"|'([^']*)'|`([^`]*)`|([^\}^\{]*?))\s*\}/g,
284
+ (match, name, paramsStr, body1, body2, body3, body4) => {
285
+ const params = paramsStr.split(',').map(p =>p.trim()).filter(p =>p);
286
+ const body = body1 ?? body2 ?? body3 ?? body4 ?? '';
287
+ defExfscss[name] = { params, body };
288
+ return ''; // Remove the define block from the output. FIGSH-FSCSS
289
+ }
290
+ );
291
+
292
+ // Now replace all @name(...) usages with their expanded bodies. FIGSH-FSCSS
293
+ processed = processed.replace(
294
+ /@([\w\_\-\—]+)\s*\(([\s\S]*?)\)/g,
295
+ (match, name, argsStr) => {
296
+ const def = defExfscss[name];
297
+ if (!def){
298
+ return match;
299
+ }// Leave unknown Def macros unchanged. FIGSH-FSCSS
300
+
301
+ const args = argsStr?.split(',').map(a => a.trim());
302
+ if(args[0]==='') args[0] = undefined;
303
+ let result = def.body;
304
+
305
+ /* Replace each @use(param) with the corresponding argument. FIGSH-FSCSS */
306
+ let xfVal = [];
307
+ def.params.forEach((param, index) => {
308
+ const df = def.params[index];
309
+ if(df&&df.includes(':')){
310
+ xfVal = df?.split(':')?.map(i=>i.trim()).filter(i=>i);
311
+ }
312
+
313
+ const dfv = xfVal[1]?xfVal[1]:'';
314
+
315
+ const arg = args[index] !== (undefined) ? args[index] : dfv;
316
+ const regex = new RegExp(`@use\\(\\s*${param.replace(/(\s+)?(\:(\s+)?.*)/g, '')}\\s*\\)`, 'g');
317
+ result = result.replace(regex, arg);
318
+ });
319
+
320
+ return result;
321
+ }
322
+ );
323
+
324
+ return processed;
325
+ }
269
326
  function procVar(vcss) {
270
327
  function processSCSS(scssCode) {
271
328
  const globalVars = {};
@@ -453,6 +510,7 @@ function procRan(input) {
453
510
  }
454
511
  });
455
512
  }
513
+
456
514
  function procArr(input) {
457
515
  // 1. Parse array declarations
458
516
  const arrayDeclarationRegex = /@arr\(?\s*([\w\-_—0-9]+)\)?\[([^\]]+)\]\)?/g;
@@ -465,6 +523,99 @@ function procArr(input) {
465
523
 
466
524
  let output = input;
467
525
 
526
+ output = output.replace(/@arr\.([\w\-_—0-9]+)(?:\!\s*\+\s*\[([^\]]+)?\])/g, (match, arrName, newArr) => {
527
+ const arr = arraysExfscss[arrName];
528
+ if (!arr) {
529
+ console.warn(`fscss[@arr] Warning: Array '${arrName}' not found.`);
530
+ return match;
531
+ }
532
+ if (!newArr) {
533
+ console.warn(
534
+ `[FSCSS Warning] @arr push failed → Invalid or empty value at "${match}"`
535
+ );
536
+ return match;
537
+ }
538
+ newItems = newArr.split(',').map(item => item.trim());
539
+ arraysExfscss[arrName].push(...newItems);
540
+ return "";
541
+ })
542
+
543
+ output = output.replace(/@arr\.([\w\-_—0-9]+)(?:\!\s*\-\s*\[([\d\w\-_—\s]+)?\])/g, (match, arrName, ind) => {
544
+ const arr = arraysExfscss[arrName];
545
+ if (!arr) {
546
+ console.warn(`fscss[@arr] Warning: Array '${arrName}' not found.`);
547
+ return match;
548
+ }
549
+ ind = Number(ind?.trim());
550
+ if (!ind||ind<1||!Number(ind)) {
551
+ console.warn(
552
+ `[FSCSS Warning] @arr splice failed → Invalid or empty index at "${match}"`
553
+ );
554
+ return match;
555
+ }
556
+ if(ind>arr.length){
557
+ console.warn(
558
+ `[FSCSS Warning] @arr → @arr.${arrName}[${ind}] is undefined at "${match}"`);
559
+ return "";
560
+ }
561
+ ind = (ind-1);
562
+ arr.splice(ind,1);
563
+ return "";
564
+ })
565
+
566
+
567
+ output = output.replace(/@arr\.([\w\-_—0-9]+)(?:\!\s*\.(length|last|reverse|first|list|indices|randint|segment|sum|unique|sort|shuffle|min|max))/g, (match, arrName, obj) => {
568
+ const arr = arraysExfscss[arrName];
569
+ if (!arr) {
570
+ console.warn(`fscss[@arr] Warning: Array '${arrName}' not found.`);
571
+ return match;
572
+ }
573
+ if(obj){
574
+ if (obj==="length") {
575
+ return arr.length;
576
+ }
577
+ if(obj==="first"){
578
+ return arr[0];
579
+ }
580
+ if (obj==="last") {
581
+ return arr.at(-1);
582
+ }
583
+ if (obj==="indices") {
584
+ return Array(arr.length).fill().map((_, i)=>(i+1)*1);
585
+ }
586
+ if (obj==="list") {
587
+ return arr.join(',');
588
+ }
589
+ if (obj==="reverse") {
590
+ return arr.toReversed().join(',');
591
+ }
592
+ if (obj==="randint") {
593
+ return arr[Math.floor(Math.random() * arr.length)];
594
+ }
595
+ if(obj==="segment") {
596
+ return arr.map(u => `[${u}]`).join('')
597
+ }
598
+ if (obj === "unique") {
599
+ return [...new Set(arr)].join(',');
600
+ }
601
+ if (obj === "sort") {
602
+ return arr.slice().sort().join(',');
603
+ }
604
+ if (obj === "shuffle") {
605
+ return arr.slice().sort(() => Math.random() - 0.5).join(',');
606
+ }
607
+ if (obj === "sum") {
608
+ return arr.reduce((a, b) => a + Number(b), 0);
609
+ }
610
+ if (obj === "min") {
611
+ return Math.min(...arr.map(Number));
612
+ }
613
+ if (obj === "max") {
614
+ return Math.max(...arr.map(Number));
615
+ }
616
+ }
617
+ })
618
+
468
619
  // 2. Process loops using @arr.name[]
469
620
  output = output.replace(/([^\{\}]+)\{\s*([^}]*@arr\.([\w\-_—0-9]+)\[\][^}]*)\s*\}/g,
470
621
  (fullMatch, selector, content, arrayName) => {
@@ -493,8 +644,49 @@ function procArr(input) {
493
644
  return arr[idx] !== undefined ? arr[idx] : fullMatch;
494
645
  });
495
646
 
647
+ output = output.replace(/@arr\.([\w\-_—0-9]+)(?:!\s*\.unit)(?:\(([^)]*)\))/g,
648
+ (fullMatch, arrayName, pl) => {
649
+ const arr = arraysExfscss[arrayName];
650
+ if (!arr) {
651
+ console.warn(`fscss[@arr] Warning: Array '${arrayName}' not found for direct access.`);
652
+ return fullMatch;
653
+ }
654
+ const sep = (pl !== undefined && pl !== "") ? pl : ' ';
655
+ return arr.map(u=>`${u+sep}`).join(',');
656
+ });
657
+
658
+ output = output.replace(/@arr\.([\w\-_—0-9]+)(?:!\s*\.prefix)(?:\(([^)]*)\))/g,
659
+ (fullMatch, arrayName, pl) => {
660
+ const arr = arraysExfscss[arrayName];
661
+ if (!arr) {
662
+ console.warn(`fscss[@arr] Warning: Array '${arrayName}' not found for direct access.`);
663
+ return fullMatch;
664
+ }
665
+ const sep = (pl !== undefined && pl !== "") ? pl : ' ';
666
+ return arr.map(u=>`${sep+u}`).join(',');
667
+ });
668
+
669
+
670
+
671
+ output = output.replace(/@arr\.([\w\-_—0-9]+)(?:!\s*\.surround)(?:\(([^)]+)\))/g,
672
+ (fullMatch, arrayName, sur) => {
673
+ const arr = arraysExfscss[arrayName];
674
+ if (!arr) {
675
+ console.warn(`fscss[@arr] Warning: Array '${arrayName}' not found for direct access.`);
676
+ return fullMatch;
677
+ }
678
+ if(!sur||sur===undefined||sur===""||!sur.includes(",")){
679
+ console.warn(
680
+ `[FSCSS Warning] @arr surround failed → Invalid or empty value at "${fullMatch}"`);
681
+ return fullMatch;
682
+ }
683
+ surArr = sur.split(',');
684
+ return arr.map(u=>`${surArr[0]+u+surArr.at(-1)}`).join(' ');
685
+ });
686
+
687
+
496
688
  // 4. Direct array access: @arr.name or @arr.name(separator)
497
- output = output.replace(/@arr\.([\w\-_—0-9]+)(?:\(([^)]*)\))?/g,
689
+ output = output.replace(/@arr\.([\w\-_—0-9]+)(?:!\s*\.join)?(?:\(([^)]*)\))/g,
498
690
  (fullMatch, arrayName, separator) => {
499
691
  const arr = arraysExfscss[arrayName];
500
692
  if (!arr) {
@@ -504,8 +696,18 @@ function procArr(input) {
504
696
  const sep = (separator !== undefined && separator !== "") ? separator : ' ';
505
697
  return arr.join(sep);
506
698
  });
507
-
508
- // 5. Clean up array declarations
699
+ output = output.replace(/@arr\.([\w\-_—0-9]+)(!)?/g, (match, arrName, fos)=>{
700
+ const arr = arraysExfscss[arrName];
701
+ if (!arr) {
702
+ console.warn(`fscss[@arr] Warning: Array '${arrName}' not found for direct access.`);
703
+ return match;
704
+ }
705
+ if(fos){
706
+ return match;
707
+ }
708
+ return arr.join(' ');
709
+ })
710
+ // Clean up array declarations
509
711
  return output
510
712
  .replace(arrayDeclarationRegex, '')
511
713
  .replace(/\n{3,}/g, '\n\n')
@@ -1113,6 +1315,6 @@ function execObj(css){
1113
1315
  }
1114
1316
 
1115
1317
  export { initlibraries,
1116
- impSel, procImp, replaceRe, procExt, procVar,procFun, procArr, procEv, procRan, transformCssValues, procNum, vfc, applyFscssTransformations,procExC, procCnt, procChe, execObj
1318
+ impSel, procImp, replaceRe, procExt, procVar,procFun, procArr, procEv, procRan, transformCssValues, procNum, vfc, applyFscssTransformations,procExC, procCnt, procDef, procChe, execObj
1117
1319
  }
1118
1320
 
package/lib/processor.js CHANGED
@@ -13,7 +13,8 @@ import {
13
13
  vfc,
14
14
  applyFscssTransformations,
15
15
  procExC,
16
- procCnt,
16
+ procCnt,
17
+ procDef,
17
18
  procChe,
18
19
  execObj
19
20
  } from "./functions/all.js";
@@ -36,6 +37,7 @@ export async function processFscss(css, options = {}) {
36
37
  if(!css.includes("exec.obj.block(fun)"))css = procFun(css);
37
38
  if(!css.includes("exec.obj.block(length)"))css = procChe(css);
38
39
  if(!css.includes("exec.obj.block(count)"))css = procCnt(css);
40
+ if(!css.includes("exec.obj.block(define)"))css = procDef(css);
39
41
  if(!css.includes("exec.obj.block(arr)"))css = procArr(css);
40
42
  if(!css.includes("exec.obj.block(event)"))css = procEv(css);
41
43
  if(!css.includes("exec.obj.block(random)"))css = procRan(css);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fscss",
3
3
  "description": "Figured Shorthand Cascading Style Sheet",
4
- "version": "1.1.13",
4
+ "version": "1.1.15",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "bin": {
@@ -21,7 +21,8 @@
21
21
  "fs-css",
22
22
  "fscss",
23
23
  "xfscss",
24
- "preprocessor"
24
+ "preprocessor",
25
+ "lightweight"
25
26
  ],
26
27
  "author": "Figsh",
27
28
  "license": "MIT",