@squeditor/squeditor-framework 1.0.4 → 1.0.5

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
@@ -4,12 +4,12 @@ We implement AI Agents skills to help you build your website easily in minutes.
4
4
 
5
5
  ### Showcase and Demo
6
6
 
7
- [Main Demo](https://squeditor.com/showcase/main-demo/)
8
- [All Components](https://squeditor.com/showcase/all-components/)
9
- [Style Guide](https://squeditor.com/showcase/style-guide/)
7
+ [Main Demo](https://squeditor.com/showcase/main-demo/) |
8
+ [All Components](https://squeditor.com/showcase/all-components/) |
9
+ [Style Guide](https://squeditor.com/showcase/style-guide/) |
10
10
  [GSAP Animations](https://squeditor.com/showcase/gsap-animations/)
11
11
 
12
- [Full Documentation](https://docs.squeditor.com)
12
+ [Full Documentation](https://docs.squeditor.com/framework/getting-started/introduction)
13
13
 
14
14
  ### Key Features
15
15
 
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@squeditor/squeditor-framework",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Squeditor Framework is a high-performance, developer-first framework for building lightning-fast, static websites. It combines the power of PHP-style templating with the modern performance of Tailwind CSS, the interactivity of UIKit 3, and the speed of Vite.",
5
5
  "main": "index.js",
6
6
  "publishConfig": {
7
7
  "access": "public"
8
8
  },
9
9
  "scripts": {
10
+ "scaffold": "node scripts/scaffold.js",
10
11
  "test": "echo \"Error: no test specified\" && exit 1"
11
12
  },
12
13
  "repository": {
@@ -0,0 +1,2 @@
1
+ /* Add your custom fonts @font-face or cdn urls here to load your fonts */
2
+ /* For local fonts use this correct path ’../static/fonts/your-font-name/..’ */
@@ -24,7 +24,8 @@ h6,
24
24
  font-family: var(--sq-font-heading);
25
25
  color: var(--sq-color-heading-text);
26
26
  font-weight: 600;
27
- line-height: 1.2;
27
+ line-height: var(--sq-heading-line-height, 1.2);
28
+ letter-spacing: var(--sq-heading-letter-spacing, normal);
28
29
  }
29
30
 
30
31
  h1 {
@@ -75,7 +76,8 @@ h6 {
75
76
  // Only apply paragraph and list styles if the author didn't supply their own layout classes
76
77
  p:not([class]) {
77
78
  margin-bottom: 1rem;
78
- line-height: 1.6;
79
+ line-height: var(--sq-body-line-height, 1.6);
80
+ letter-spacing: var(--sq-body-letter-spacing, normal);
79
81
  }
80
82
 
81
83
  ul:not([class]),
@@ -115,7 +115,7 @@
115
115
  }
116
116
  }
117
117
 
118
- .sq--header {
118
+ .sq-header {
119
119
  z-index: var(--sq-z-sticky);
120
120
 
121
121
  &--sticky {
@@ -133,7 +133,6 @@
133
133
  // ---------------------------------------------------------
134
134
  // Container + Expand Container
135
135
  // ---------------------------------------------------------
136
- @layer components {
137
136
  .container {
138
137
  width: 100%;
139
138
 
@@ -168,13 +167,9 @@
168
167
  overflow: visible;
169
168
  }
170
169
 
171
- }
172
-
173
170
  // ---------------------------------------------------------
174
171
  // Form icon group
175
172
  // ---------------------------------------------------------
176
- @layer components {
177
-
178
173
  /* Base */
179
174
  .form-icon-group {
180
175
  position: relative;
@@ -228,8 +223,6 @@
228
223
  [dir="rtl"] .form-icon-group.form-icon-flip .form-control.form-control-sm { padding-right: 1rem !important; padding-left: 2.25rem !important; }
229
224
  [dir="rtl"] .form-icon-group.form-icon-flip .form-control.form-control-xs { padding-right: 1rem !important; padding-left: 1.75rem !important; }
230
225
 
231
- }
232
-
233
226
  // ---------------------------------------------------------
234
227
  // Page Transitions
235
228
  // ---------------------------------------------------------
@@ -1,16 +1,17 @@
1
1
  // _tokens.scss — Design tokens as CSS custom properties
2
2
 
3
3
  // 1. Define SASS Variables for calculations
4
- $color-primary: #1c2020 !default;
5
- $color-primary-dark: #ffffff !default;
6
- $color-secondary: #038677 !default;
7
- $color-secondary-dark: #d5f37b !default;
8
- $color-accent: #F0FF44 !default;
9
- $color-accent-dark: #F0FF44 !default;
4
+ $color-primary: #107466 !default;
5
+ $color-primary-dark: #F0FF44 !default;
6
+ $color-secondary: #1c2020 !default;
7
+ $color-secondary-dark: #fef1e7 !default;
8
+ $color-accent: #e5fdc5 !default;
9
+ $color-accent-dark: #e5fdc5 !default;
10
10
  $color-white: #FFFFFF !default;
11
- $color-muted-text: #777f7f !default;
12
- $color-muted-bg: #f8f8f8 !default;
11
+ $color-muted-text: #707070 !default;
12
+ $color-muted-bg: #fef1e7 !default;
13
13
  $color-light: #f8f8f8 !default;
14
+ $color-dark: #19191b !default;
14
15
  $color-body-bg: #FFFFFF !default;
15
16
  $color-body-text: #19191b !default;
16
17
  $color-heading-text: #19191b !default;
@@ -28,6 +29,7 @@ $color-border: rgba(138, 138, 138, 0.196) !default;
28
29
  --sq-color-muted-text: #{$color-muted-text};
29
30
  --sq-color-muted-bg: #{$color-muted-bg};
30
31
  --sq-color-light: #{$color-light};
32
+ --sq-color-dark: #{$color-dark};
31
33
  --sq-color-body-bg: #{$color-body-bg};
32
34
  --sq-color-body-text: #{$color-body-text};
33
35
  --sq-color-heading-text: #{$color-heading-text};
@@ -76,12 +78,12 @@ $color-border: rgba(138, 138, 138, 0.196) !default;
76
78
  // --- Component Tokens ---
77
79
 
78
80
  // Buttons
79
- --sq-btn-height: 2.25rem; // h-9
81
+ --sq-btn-height: 2.75rem;
80
82
  --sq-btn-bg: transparent;
81
83
  --sq-btn-text: var(--sq-color-body-text);
82
- --sq-btn-radius: var(--sq-radius-lg);
83
- --sq-btn-font-size: 1rem; // text-base
84
- --sq-btn-font-weight: 500;
84
+ --sq-btn-radius: var(--sq-radius-md);
85
+ --sq-btn-font-size: 1rem;
86
+ --sq-btn-font-weight: 600;
85
87
 
86
88
  --sq-btn-default-bg: var(--sq-color-light);
87
89
  --sq-btn-default-text: var(--sq-color-muted-text);
@@ -113,7 +115,7 @@ $color-border: rgba(138, 138, 138, 0.196) !default;
113
115
  // Dropdown
114
116
  --sq-dropdown-width: 300px;
115
117
  --sq-dropdown-padding: 2rem;
116
- --sq-dropdown-bg: var(--sq-color-white);
118
+ --sq-dropdown-bg: var(--sq-color-muted-bg);
117
119
  --sq-dropdown-text: var(--sq-color-body-text);
118
120
 
119
121
  // Accordion
@@ -226,4 +228,7 @@ $color-border: rgba(138, 138, 138, 0.196) !default;
226
228
  --sq-card-bg: #19191b;
227
229
  --sq-card-shadow: none;
228
230
  --sq-card-shadow-hover: none;
231
+
232
+ // Dropdown
233
+ --sq-dropdown-bg: var(--sq-color-muted-bg);
229
234
  }
@@ -5,6 +5,7 @@
5
5
  $site = [
6
6
  'name' => 'My Project',
7
7
  'lang' => 'en',
8
+ 'dir' => 'ltr', // 'ltr' or 'rtl'
8
9
  'logo' => 'assets/static/images/logo.svg',
9
10
  'description' => 'Squeditor project starter template.',
10
11
  'og_image' => 'assets/static/images/og-default.png',
@@ -41,10 +41,10 @@ ob_start();
41
41
  </p>
42
42
 
43
43
  <div class="flex items-center justify-center gap-4" data-gsap="position: '<-0.5'; from: {y: 20, opacity: 0, filter: 'blur(5px)'}">
44
- <a href="https://squeditor.com/" class="btn btn-lg btn-secondary !px-8 !py-3 !rounded-full text-white font-medium hover:scale-105 transition-transform">
44
+ <a href="https://squeditor.com/" class="btn btn-lg btn-secondary hover:scale-105 transition-transform">
45
45
  Try Squeditor
46
46
  </a>
47
- <a href="https://docs.squeditor.com/" class="btn btn-lg !px-8 !py-3 !rounded-full text-white font-medium !border !border-1 !border-solid !border-zinc-200 hover:scale-105 transition-transform">
47
+ <a href="https://docs.squeditor.com/" class="btn btn-lg !border !border-1 !border-solid !border-zinc-200 hover:scale-105 transition-transform">
48
48
  View Docs
49
49
  </a>
50
50
  </div>
@@ -40,14 +40,16 @@ if (file_exists(__DIR__ . '/../config/active-slider.php')) {
40
40
  <?php if ($is_vite): ?>
41
41
  <!-- Vite Development Environment -->
42
42
  <script type="module" src="<?= $vite_server ?>/@vite/client"></script>
43
- <link rel="stylesheet" href="<?= $vite_server ?>/assets/css/tailwind.css">
43
+ <link rel="stylesheet" href="<?= $vite_server ?>/assets/css/fonts.css">
44
44
  <link rel="stylesheet" href="<?= $vite_server ?>/assets/css/squeditor-icons.css">
45
+ <link rel="stylesheet" href="<?= $vite_server ?>/assets/css/tailwind.css">
45
46
  <?php if ($active_slider): ?><link rel="stylesheet" href="<?= $vite_server ?>/assets/css/slider.min.css"><?php endif; ?>
46
47
  <script type="module" src="<?= $vite_server ?>/assets/scss/main.scss"></script>
47
48
  <style>html.js-fouc { opacity: 0; transition: opacity 0.15s ease-out; }</style>
48
49
  <script>document.documentElement.classList.add('js-fouc');</script>
49
50
  <?php else: ?>
50
51
  <!-- Production Static Assets -->
52
+ <link rel="stylesheet" href="assets/css/fonts.css">
51
53
  <link rel="stylesheet" href="assets/css/squeditor-icons.css">
52
54
  <link rel="stylesheet" href="assets/css/tailwind.css">
53
55
  <?php if ($active_slider): ?><link rel="stylesheet" href="assets/css/slider.min.css"><?php endif; ?>
@@ -17,7 +17,7 @@ $items = $items ?? [];
17
17
  <li class="flex items-center gap-2"><i class="sq-icon-chevron-right opacity-30"></i> <?= htmlspecialchars($feature) ?></li>
18
18
  <?php endforeach; ?>
19
19
  </ul>
20
- <span class="absolute top-6 end-6 w-10 h-10 p-0 rounded-full flex items-center justify-center border border-zinc-200 dark:border-zinc-800 group-hover:-rotate-45 transition-transform duration-300">
20
+ <span class="absolute top-6 end-6 w-10 h-10 p-0 rounded-full flex items-center justify-center bg-white group-hover:-rotate-45 transition-transform duration-300">
21
21
  <i class="sq-icon-arrow-right"></i>
22
22
  </span>
23
23
  </div>
@@ -7,7 +7,7 @@ $button_url = $button_url ?? '#';
7
7
  $secondary_button_text = $secondary_button_text ?? '';
8
8
  $hint_text = $hint_text ?? '';
9
9
  ?>
10
- <section class="py-32 text-center border-t border-zinc-300 border-opacity-30 dark:border-opacity-5">
10
+ <section class="sq-cta-banner py-16 md:py-24 lg:py-32 text-center border-t border-zinc-300 border-opacity-30 dark:border-opacity-5">
11
11
  <div class="max-w-4xl mx-auto px-6">
12
12
  <h2 class="text-4xl md:text-5xl font-bold mb-4 tracking-tighter">
13
13
  <?= $heading ?>
@@ -3,7 +3,7 @@
3
3
  $heading = $heading ?? 'Subscribe to our newsletter';
4
4
  $subheading = $subheading ?? 'Get the latest updates and news from our team.';
5
5
  ?>
6
- <section class="py-20 bg-zinc-50 dark:bg-zinc-800 dark:bg-opacity-40">
6
+ <section class="py-20 bg-muted dark:bg-opacity-40">
7
7
  <div class="max-w-7xl mx-auto px-6 flex flex-col items-center justify-between gap-8">
8
8
  <div class="mb-8 md:mb-0 md:w-1/2">
9
9
  <h2 class="text-4xl font-bold text-center m-0"><?= htmlspecialchars($heading) ?></h2>
@@ -4,7 +4,7 @@
4
4
  $isDark = $isDark ?? false;
5
5
  $isFloat = $isFloat ?? false;
6
6
 
7
- $headerClasses = 'sq--header w-full z-[1000]';
7
+ $headerClasses = 'sq-header w-full z-[1000]';
8
8
  if ($isFloat) $headerClasses .= ' absolute top-0';
9
9
  if ($isDark) $headerClasses .= ' dark-mode text-white bg-zinc-900';
10
10
  else $headerClasses .= ' bg-white border-b';
@@ -62,13 +62,13 @@ $processed_heading = str_replace(
62
62
  </h2>
63
63
 
64
64
  <!-- Subheading -->
65
- <p class="text-lg md:text-xl text-muted mb-10 max-w-md leading-relaxed"
65
+ <p class="text-lg md:text-xl text-muted mb-10 max-w-md"
66
66
  data-gsap="from: {opacity: 0, y: 20}; duration: 0.8; delay: 0.4">
67
67
  <?= htmlspecialchars($args['subheading']) ?>
68
68
  </p>
69
69
 
70
70
  <!-- CTA Button -->
71
- <div data-gsap="from: {opacity: 0, y: 16}; duration: 0.6; delay: 0.7" class="self-start mb-16">
71
+ <div data-gsap="from: {opacity: 0, y: 16}; duration: 0.6; delay: 0.7" class="self-start mb-8 lg:mb-16">
72
72
  <a href="<?= htmlspecialchars($args['cta_url']) ?>" class="btn btn-secondary min-h-[48px] !px-8 !py-4 !text-base !shadow-lg !shadow-sq-primary/30 flex items-center gap-2 transition-transform hover:scale-105">
73
73
  <?= htmlspecialchars($args['cta_label']) ?>
74
74
  <i class="sq-icon sq-icon-arrow-up-right text-lg leading-none mt-0.5"></i>
@@ -96,8 +96,8 @@ $processed_heading = str_replace(
96
96
  <div class="relative h-[400px] md:h-[700px]">
97
97
 
98
98
  <!-- Image Wrapper -->
99
- <div class="h-full rounded-[2rem] overflow-hidden" data-gsap="from: {clipPath: 'inset(0 0 100% 0)'}; duration: 2; ease: expo.inOut;">
100
- <img src="<?= htmlspecialchars($args['image_src']) ?>" alt="<?= htmlspecialchars($args['image_alt']) ?>" class="w-full h-full object-cover rounded-[2rem]">
99
+ <div class="h-full rounded-3xl overflow-hidden" data-gsap="from: {clipPath: 'inset(0 0 100% 0)'}; duration: 2; ease: expo.inOut;">
100
+ <img src="<?= htmlspecialchars($args['image_src']) ?>" alt="<?= htmlspecialchars($args['image_alt']) ?>" class="w-full h-full object-cover">
101
101
  </div>
102
102
 
103
103
  <!-- Floating Services Container -->
@@ -9,8 +9,8 @@ if ($layout !== 'default') {
9
9
  }
10
10
  ?>
11
11
  <!-- Site Footer -->
12
- <footer id="sq_footer" class="sq--footer py-24 border-t dark:border-transparent dark:bg-black/40">
13
- <div class="sq--footer--inner max-w-7xl mx-auto px-6 grid grid-cols-1 md:grid-cols-5 gap-12 text-body">
12
+ <footer id="sq_footer" class="sq-footer py-12 md:py-18 lg:py-24 border-t dark:border-transparent dark:bg-black/40">
13
+ <div class="sq-footer-inner max-w-7xl mx-auto px-6 grid grid-cols-1 md:grid-cols-5 gap-6 md:gap-8 lg:gap-12">
14
14
  <div class="sq--footer--brand md:col-span-2">
15
15
  <div class="flex items-center gap-2 mb-6">
16
16
  <a href="index.html" class="sq--logo flex items-center gap-2 group">
@@ -20,7 +20,7 @@ if ($layout !== 'default') {
20
20
  <h1 class="font-bold text-xl m-0 tracking-tight"><?= htmlspecialchars($site['name']) ?></h1>
21
21
  </a>
22
22
  </div>
23
- <p class="text-sm max-w-xs leading-relaxed mb-8">
23
+ <p class="text-sm max-w-xs leading-relaxed mb-6">
24
24
  <?= htmlspecialchars($site['description']) ?>
25
25
  </p>
26
26
  <div class="flex gap-4">
@@ -61,11 +61,11 @@ if ($layout !== 'default') {
61
61
  </ul>
62
62
  </div>
63
63
  </div>
64
- <div class="sq--footer--divider max-w-7xl mx-auto px-6 mt-20 mb-8">
64
+ <div class="sq-footer-divider max-w-7xl mx-auto px-6 mt-8 md:mt-12 lg:mt-16 mb-8">
65
65
  <hr>
66
66
  </div>
67
- <div class="sq--footer--bottom max-w-7xl mx-auto px-6 flex flex-col md:flex-row justify-between items-center gap-4 text-xs">
68
- <p>&copy; <?= date('Y') ?> <?= htmlspecialchars($site['name']) ?>. Built locally by Developers.</p>
67
+ <div class="sq-footer-bottom max-w-7xl mx-auto px-6 flex flex-col md:flex-row justify-between items-center gap-4 text-sm text-muted">
68
+ <p>&copy; <?= date('Y') ?> <?= htmlspecialchars($site['name']) ?>. Built with ❤️ by Expert Developers.</p>
69
69
  <div class="flex gap-8">
70
70
  <a href="#" class="hover:text-secondary transition-colors">Terms of Service</a>
71
71
  <a href="#" class="hover:text-secondary transition-colors">Privacy Policy</a>
@@ -11,8 +11,8 @@ if ($layout !== 'default') {
11
11
  }
12
12
  ?>
13
13
  <!-- Site Header -->
14
- <header id="sq_header" class="sq--header absolute w-full top-0 z-[1000] bg-white dark:bg-zinc-900" data-gsap="from: {y: -80, opacity: 0}; to: {y: 0, opacity: 1}; duration: 1.2; ease: expo.inOut;">
15
- <div class="sq--header--inner max-w-7xl mx-auto px-6 h-20 flex items-center justify-between">
14
+ <header id="sq_header" class="sq-header absolute w-full top-0 z-[1000]" data-gsap="from: {y: -80, opacity: 0}; to: {y: 0, opacity: 1}; duration: 1.2; ease: expo.inOut;">
15
+ <div class="sq-header-inner max-w-7xl mx-auto px-6 h-20 flex items-center justify-between">
16
16
 
17
17
  <!-- Logo -->
18
18
  <a href="index.html" class="sq--logo flex items-center gap-2 group">
@@ -23,17 +23,17 @@ if ($layout !== 'default') {
23
23
  </a>
24
24
 
25
25
  <!-- Desktop Nav (Centered) -->
26
- <div class="sq--header--nav hidden md:flex items-center absolute left-1/2 -translate-x-1/2">
26
+ <div class="sq-header-nav items-center absolute left-1/2 -translate-x-1/2 hidden lg:flex">
27
27
  <?php get_template_part('nav'); ?>
28
28
  </div>
29
29
 
30
30
  <!-- Right Side / CTA -->
31
- <div class="sq--header--cta flex items-center gap-6">
31
+ <div class="sq-header-cta flex items-center gap-6">
32
32
  <a href="#" class="sq-nav-link text-base font-medium text-zinc-900 dark:text-white !text-opacity-70 hover:text-secondary hover:!text-opacity-100 transition-colors hidden md:inline-block">Log in</a>
33
33
  <a href="https://squeditor.com/" class="btn btn-secondary !hidden md:!inline-flex">Try Squeditor</a>
34
34
 
35
35
  <!-- Mobile Toggle -->
36
- <button class="sq--header--mobile--toggle md:hidden" data-gsap-toggle="#sq_offcanvas_creative" type="button" aria-label="Menu">
36
+ <button class="sq-header-mobile-toggle md:hidden" data-gsap-toggle="#sq_offcanvas_creative" type="button" aria-label="Menu">
37
37
  <span data-uk-icon="icon: menu; ratio: 1.5"></span>
38
38
  </button>
39
39
  </div>
@@ -1,13 +1,13 @@
1
1
  <?php
2
2
  // src/template-parts/nav.php
3
3
  $is_mobile = $mobile ?? false;
4
- $nav_class = $is_mobile ? 'flex flex-col space-y-4' : 'flex space-x-2 items-center m-0 p-0';
4
+ $nav_class = $is_mobile ? 'flex flex-col space-y-4' : 'flex space-x-8 items-center m-0 p-0';
5
5
  ?>
6
6
  <nav>
7
7
  <ul class="<?= $nav_class ?>">
8
8
  <?php foreach ($site['nav'] as $item): ?>
9
9
  <li>
10
- <a href="<?= htmlspecialchars($item['url']) ?>" class="sq-nav-link text-base font-medium text-zinc-900 dark:text-white !text-opacity-70 hover:text-secondary hover:!text-opacity-100 transition-colors py-2 px-3">
10
+ <a href="<?= htmlspecialchars($item['url']) ?>" class="sq-nav-link">
11
11
  <?= htmlspecialchars($item['label']) ?>
12
12
  </a>
13
13
  </li>
@@ -2,7 +2,7 @@
2
2
  // src/template-parts/page-title-bar.php
3
3
  $title = $title ?? 'Page Title';
4
4
  $subtitle = $subtitle ?? '';
5
- $class = $class ?? 'py-20 text-center bg-zinc-50 dark:bg-zinc-800 dark:bg-opacity-40';
5
+ $class = $class ?? 'py-20 text-center bg-muted dark:bg-opacity-40';
6
6
  ?>
7
7
  <div class="<?= htmlspecialchars($class) ?>">
8
8
  <div class="max-w-7xl mx-auto px-6">
@@ -19,6 +19,7 @@ export default defineConfig({
19
19
  main_css: path.resolve(__dirname, 'src/assets/scss/main.scss'),
20
20
  tailwind: path.resolve(__dirname, 'src/assets/css/tailwind.css'),
21
21
  'squeditor-icons': path.resolve(__dirname, 'src/assets/css/squeditor-icons.css'),
22
+ 'fonts': path.resolve(__dirname, 'src/assets/css/fonts.css'),
22
23
  },
23
24
  output: {
24
25
  entryFileNames: 'assets/js/[name].js',
@@ -60,6 +61,13 @@ export default defineConfig({
60
61
  name: 'php-watch',
61
62
  handleHotUpdate({ file, server }) {
62
63
  if (file.endsWith('.php')) {
64
+ // Force Vite to invalidate CSS modules so Tailwind generates new classes
65
+ const tailwindModule = server.moduleGraph.getModuleById(path.resolve(__dirname, 'src/assets/css/tailwind.css'));
66
+ if (tailwindModule) server.moduleGraph.invalidateModule(tailwindModule);
67
+
68
+ const scssModule = server.moduleGraph.getModuleById(path.resolve(__dirname, 'src/assets/scss/main.scss'));
69
+ if (scssModule) server.moduleGraph.invalidateModule(scssModule);
70
+
63
71
  server.ws.send({ type: 'full-reload' });
64
72
  }
65
73
  }
@@ -77,8 +77,7 @@ scssPaths.forEach(f => {
77
77
  fs.writeFileSync(path.join(outputJsDir, 'uikit-components.js'), jsBundle);
78
78
  fs.writeFileSync(path.join(outputScssDir, '_uikit_dynamic.scss'), scssImports);
79
79
 
80
- console.log('[Squeditor] ✅ uikit-components.js and _uikit_dynamic.scss built successfully.');
81
- console.log(` Components included: _core, ${selectedComponents.join(', ')}`);
80
+ console.log('[Squeditor] ✅ UIkit3 components built successfully.');
82
81
 
83
82
  // Generate src/config/active-components.php for the style-guide page
84
83
  const phpConfigDir = path.join(projectRoot, 'src/config');
@@ -128,7 +127,7 @@ if (fs.existsSync(mainScssPath) && config.themes) {
128
127
  // Ensure exactly one trailing newline
129
128
  mainScss = mainScss.trim() + '\n' + themeImports;
130
129
  fs.writeFileSync(mainScssPath, mainScss);
131
- console.log(`[Squeditor] 🎨 Injected themes: ${Object.keys(config.themes).join(', ')}`);
130
+ console.log(`[Squeditor] 🎨 Ready themes: ${Object.keys(config.themes).join(', ')}`);
132
131
  }
133
132
 
134
133
  // Generate Dynamic Slider Config Import
@@ -141,7 +140,7 @@ if (sliderConfig.library === 'swiper') {
141
140
  sliderImportCode += 'import \'./modules/splide-init.js\';\n';
142
141
  }
143
142
  fs.writeFileSync(dynamicSliderPath, sliderImportCode);
144
- console.log(`[Squeditor] 🎠 Injected slider library: ${sliderConfig.library || 'none'}`);
143
+ console.log(`[Squeditor] 🎠 Selected slider library: ${sliderConfig.library || 'none'}`);
145
144
 
146
145
  // Copy slider library CSS to src/assets/css/slider.min.css
147
146
  // This keeps the CSS separate from main.js and gives it a clear, descriptive filename
@@ -150,7 +149,6 @@ if (sliderConfig.library === 'splide') {
150
149
  const splideCssPath = path.join(projectRoot, 'node_modules/@splidejs/splide/dist/css/splide.min.css');
151
150
  if (fs.existsSync(splideCssPath)) {
152
151
  fs.copyFileSync(splideCssPath, sliderCssDest);
153
- console.log('[Squeditor] 📎 Copied Splide CSS → src/assets/css/slider.min.css');
154
152
  } else {
155
153
  console.warn('[Squeditor] ⚠️ Splide CSS not found at expected path.');
156
154
  fs.writeFileSync(sliderCssDest, '/* Splide CSS not found */\n');
@@ -172,7 +170,6 @@ if (sliderConfig.library === 'splide') {
172
170
  }
173
171
  }
174
172
  fs.writeFileSync(sliderCssDest, combinedCss);
175
- console.log('[Squeditor] 📎 Copied Swiper CSS → src/assets/css/slider.min.css');
176
173
  } else {
177
174
  // No slider configured — write an empty placeholder so head.php link doesn't 404
178
175
  fs.writeFileSync(sliderCssDest, '/* No slider library configured */\n');
@@ -14,7 +14,24 @@ if (!projectName) {
14
14
  let destIndex = args.indexOf('--dest');
15
15
  let destPath = destIndex !== -1 ? args[destIndex + 1] : projectName;
16
16
  const sourceDir = path.join(__dirname, '..', 'project-template');
17
- const targetDir = path.resolve(process.cwd(), destPath);
17
+
18
+ // Check if running directly inside the cloned framework repository
19
+ let isInsideRepo = false;
20
+ try {
21
+ const pkgPath = path.join(process.cwd(), 'package.json');
22
+ if (fs.existsSync(pkgPath)) {
23
+ const pkg = require(pkgPath);
24
+ if (pkg.name === '@squeditor/squeditor-framework') {
25
+ isInsideRepo = true;
26
+ }
27
+ }
28
+ } catch (e) {}
29
+
30
+ // If running inside the repo, scaffold as a sibling (../destPath).
31
+ // Otherwise scaffold in the current directory.
32
+ const targetDir = isInsideRepo
33
+ ? path.resolve(process.cwd(), '..', destPath)
34
+ : path.resolve(process.cwd(), destPath);
18
35
 
19
36
  if (!fs.existsSync(sourceDir)) {
20
37
  console.error(`Source template directory does not exist: ${sourceDir}`);
@@ -47,14 +64,18 @@ function copyDirectory(src, dest, ignoreList = []) {
47
64
  console.log(`[Squeditor] Scaffolding new project: ${projectName}...`);
48
65
 
49
66
  // 1. Copy the framework core
50
- const frameworkSourceDir = path.join(__dirname, '..');
51
- const frameworkTargetDir = path.resolve(process.cwd(), 'squeditor-framework');
52
-
53
- if (!fs.existsSync(frameworkTargetDir)) {
54
- console.log(`[Squeditor] Installing local framework core at ./squeditor-framework...`);
55
- // Pass the name of the target directory to the ignore list to prevent infinite loop
56
- const ignoreCoreList = ['project-template', 'showcase', 'node_modules', '.git', '.github', 'squeditor-framework'];
57
- copyDirectory(frameworkSourceDir, frameworkTargetDir, ignoreCoreList);
67
+ if (!isInsideRepo) {
68
+ const frameworkSourceDir = path.join(__dirname, '..');
69
+ const frameworkTargetDir = path.resolve(process.cwd(), 'squeditor-framework');
70
+
71
+ if (!fs.existsSync(frameworkTargetDir)) {
72
+ console.log(`[Squeditor] Installing local framework core at ./squeditor-framework...`);
73
+ // Pass the name of the target directory to the ignore list to prevent infinite loop
74
+ const ignoreCoreList = ['project-template', 'showcase', 'node_modules', '.git', '.github', 'squeditor-framework'];
75
+ copyDirectory(frameworkSourceDir, frameworkTargetDir, ignoreCoreList);
76
+ }
77
+ } else {
78
+ console.log(`[Squeditor] Running inside framework repo. Skipping core installation (using repo).`);
58
79
  }
59
80
 
60
81
  // 2. Copy the project template