@sociallane/elements 1.0.12 → 1.0.13
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.
|
@@ -55,13 +55,13 @@ cd wp-content/plugins/sociallane-elements && npm install && npm run build
|
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
57
|
# From your WordPress root (directory that contains wp-content)
|
|
58
|
-
npx @sociallane/elements --
|
|
58
|
+
npx @sociallane/elements --base
|
|
59
59
|
```
|
|
60
60
|
|
|
61
61
|
Then add widgets by slug (no manual `widgets.json` editing):
|
|
62
62
|
|
|
63
63
|
```bash
|
|
64
|
-
npx @sociallane/elements add hero-split faq content-block widget-filter
|
|
64
|
+
npx @sociallane/elements add hero-split faq-stacked content-block widget-filter
|
|
65
65
|
```
|
|
66
66
|
|
|
67
67
|
Each `add` updates `widgets.json` and runs the build. You can run `add` anytime to add more widgets.
|
|
@@ -77,8 +77,8 @@ This copies the full plugin to `wp-content/plugins/sociallane-elements`, runs `n
|
|
|
77
77
|
**Custom path:**
|
|
78
78
|
|
|
79
79
|
```bash
|
|
80
|
-
npx @sociallane/elements --
|
|
81
|
-
npx @sociallane/elements add hero-split faq
|
|
80
|
+
npx @sociallane/elements --base path/to/wp-content/plugins/sociallane-elements
|
|
81
|
+
npx @sociallane/elements add --target path/to/wp-content/plugins/sociallane-elements hero-split faq-stacked
|
|
82
82
|
```
|
|
83
83
|
|
|
84
84
|
**Single widget (per-widget packages):**
|
|
@@ -87,7 +87,7 @@ You can install one widget at a time via its own package. This installs the Soci
|
|
|
87
87
|
|
|
88
88
|
```bash
|
|
89
89
|
# From your WordPress root or wp-content/plugins
|
|
90
|
-
npx @sociallane/widget-
|
|
90
|
+
npx @sociallane/widget-content-block
|
|
91
91
|
npx @sociallane/widget-faq-stacked
|
|
92
92
|
```
|
|
93
93
|
|
|
@@ -7,8 +7,11 @@ Quick reference for loading widgets via npm workspaces.
|
|
|
7
7
|
## One-liners
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
#
|
|
11
|
-
|
|
10
|
+
# Base install (no widgets imported yet)
|
|
11
|
+
npx @sociallane/elements --base
|
|
12
|
+
|
|
13
|
+
# Add selected widgets
|
|
14
|
+
npx @sociallane/elements add hero-split faq-stacked content-block
|
|
12
15
|
|
|
13
16
|
# Dev watch (rebuilds on file change)
|
|
14
17
|
npm run dev
|
|
@@ -28,7 +31,7 @@ Edit `widgets.json` at plugin root:
|
|
|
28
31
|
"hero-split",
|
|
29
32
|
"hero-overlay",
|
|
30
33
|
"content-block",
|
|
31
|
-
"faq"
|
|
34
|
+
"faq-stacked"
|
|
32
35
|
]
|
|
33
36
|
}
|
|
34
37
|
```
|
|
@@ -39,7 +42,10 @@ Only slugs listed here are loaded. Add or remove as needed.
|
|
|
39
42
|
|
|
40
43
|
## Widget → npm package & command
|
|
41
44
|
|
|
42
|
-
|
|
45
|
+
Common widgets and their npm package / add command:
|
|
46
|
+
|
|
47
|
+
> Note: per-widget packages may not all be published at the same time.
|
|
48
|
+
> The most reliable flow is `npx @sociallane/elements --base` then `npx @sociallane/elements add ...`.
|
|
43
49
|
|
|
44
50
|
| Widget | Package | Command |
|
|
45
51
|
|--------|---------|---------|
|
|
@@ -52,7 +58,9 @@ Every widget and its npm package / add command:
|
|
|
52
58
|
| cta-banner | `@sociallane/widget-cta-banner` | `npm install @sociallane/widget-cta-banner` |
|
|
53
59
|
| cta-notify | `@sociallane/widget-cta-notify` | `npm install @sociallane/widget-cta-notify` |
|
|
54
60
|
| cta-split | `@sociallane/widget-cta-split` | `npm install @sociallane/widget-cta-split` |
|
|
55
|
-
| faq | `@sociallane/widget-faq` | `npm install @sociallane/widget-faq` |
|
|
61
|
+
| faq-stacked | `@sociallane/widget-faq-stacked` | `npm install @sociallane/widget-faq-stacked` |
|
|
62
|
+
| faq-split | `@sociallane/widget-faq-split` | `npm install @sociallane/widget-faq-split` |
|
|
63
|
+
| faq-centered | `@sociallane/widget-faq-centered` | `npm install @sociallane/widget-faq-centered` |
|
|
56
64
|
| feature-grid | `@sociallane/widget-feature-grid` | `npm install @sociallane/widget-feature-grid` |
|
|
57
65
|
| feature-list | `@sociallane/widget-feature-list` | `npm install @sociallane/widget-feature-list` |
|
|
58
66
|
| feature-list-cta | `@sociallane/widget-feature-list-cta` | `npm install @sociallane/widget-feature-list-cta` |
|
|
@@ -62,25 +70,34 @@ Every widget and its npm package / add command:
|
|
|
62
70
|
| form-contact | `@sociallane/widget-form-contact` | `npm install @sociallane/widget-form-contact` |
|
|
63
71
|
| grid-case-studies | `@sociallane/widget-grid-case-studies` | `npm install @sociallane/widget-grid-case-studies` |
|
|
64
72
|
| grid-components | `@sociallane/widget-grid-components` | `npm install @sociallane/widget-grid-components` |
|
|
65
|
-
| grid
|
|
73
|
+
| posts-grid | `@sociallane/widget-posts-grid` | `npm install @sociallane/widget-posts-grid` |
|
|
74
|
+
| posts-grid-overlay | `@sociallane/widget-posts-grid-overlay` | `npm install @sociallane/widget-posts-grid-overlay` |
|
|
66
75
|
| grid-team | `@sociallane/widget-grid-team` | `npm install @sociallane/widget-grid-team` |
|
|
67
|
-
| grid
|
|
76
|
+
| testimonials-grid | `@sociallane/widget-testimonials-grid` | `npm install @sociallane/widget-testimonials-grid` |
|
|
77
|
+
| testimonials-masonry | `@sociallane/widget-testimonials-masonry` | `npm install @sociallane/widget-testimonials-masonry` |
|
|
78
|
+
| testimonials-bento | `@sociallane/widget-testimonials-bento` | `npm install @sociallane/widget-testimonials-bento` |
|
|
68
79
|
| hero-announcement | `@sociallane/widget-hero-announcement` | `npm install @sociallane/widget-hero-announcement` |
|
|
69
80
|
| hero-centered-image | `@sociallane/widget-hero-centered-image` | `npm install @sociallane/widget-hero-centered-image` |
|
|
70
81
|
| hero-collage | `@sociallane/widget-hero-collage` | `npm install @sociallane/widget-hero-collage` |
|
|
71
82
|
| hero-overlay | `@sociallane/widget-hero-overlay` | `npm install @sociallane/widget-hero-overlay` |
|
|
72
|
-
| hero-saas | `@sociallane/widget-hero-saas` | `npm install @sociallane/widget-hero-saas` |
|
|
83
|
+
| hero-saas-split | `@sociallane/widget-hero-saas-split` | `npm install @sociallane/widget-hero-saas-split` |
|
|
84
|
+
| hero-saas-stacked | `@sociallane/widget-hero-saas-stacked` | `npm install @sociallane/widget-hero-saas-stacked` |
|
|
85
|
+
| hero-saas-centered | `@sociallane/widget-hero-saas-centered` | `npm install @sociallane/widget-hero-saas-centered` |
|
|
73
86
|
| hero-split | `@sociallane/widget-hero-split` | `npm install @sociallane/widget-hero-split` |
|
|
74
87
|
| hero-stacked-image | `@sociallane/widget-hero-stacked-image` | `npm install @sociallane/widget-hero-stacked-image` |
|
|
75
88
|
| intro-pattern | `@sociallane/widget-intro-pattern` | `npm install @sociallane/widget-intro-pattern` |
|
|
76
89
|
| intro-text | `@sociallane/widget-intro-text` | `npm install @sociallane/widget-intro-text` |
|
|
77
|
-
| logo-grid | `@sociallane/widget-logo-grid` | `npm install @sociallane/widget-logo-grid` |
|
|
90
|
+
| logo-grid-centered | `@sociallane/widget-logo-grid-centered` | `npm install @sociallane/widget-logo-grid-centered` |
|
|
91
|
+
| logo-grid-row | `@sociallane/widget-logo-grid-row` | `npm install @sociallane/widget-logo-grid-row` |
|
|
92
|
+
| logo-grid-split | `@sociallane/widget-logo-grid-split` | `npm install @sociallane/widget-logo-grid-split` |
|
|
78
93
|
| nav-default | `@sociallane/widget-nav-default` | `npm install @sociallane/widget-nav-default` |
|
|
79
94
|
| nav-centered | `@sociallane/widget-nav-centered` | `npm install @sociallane/widget-nav-centered` |
|
|
80
95
|
| nav-minimal | `@sociallane/widget-nav-minimal` | `npm install @sociallane/widget-nav-minimal` |
|
|
81
96
|
| nav-compact | `@sociallane/widget-nav-compact` | `npm install @sociallane/widget-nav-compact` |
|
|
82
97
|
| nav-floating | `@sociallane/widget-nav-floating` | `npm install @sociallane/widget-nav-floating` |
|
|
83
98
|
| newsletter | `@sociallane/widget-newsletter` | `npm install @sociallane/widget-newsletter` |
|
|
99
|
+
| newsletter-card | `@sociallane/widget-newsletter-card` | `npm install @sociallane/widget-newsletter-card` |
|
|
100
|
+
| newsletter-section | `@sociallane/widget-newsletter-section` | `npm install @sociallane/widget-newsletter-section` |
|
|
84
101
|
| outreach-dashboard | `@sociallane/widget-outreach-dashboard` | `npm install @sociallane/widget-outreach-dashboard` |
|
|
85
102
|
| pipeline-dashboard | `@sociallane/widget-pipeline-dashboard` | `npm install @sociallane/widget-pipeline-dashboard` |
|
|
86
103
|
| pricing-table | `@sociallane/widget-pricing-table` | `npm install @sociallane/widget-pricing-table` |
|
|
@@ -89,7 +106,9 @@ Every widget and its npm package / add command:
|
|
|
89
106
|
| services | `@sociallane/widget-services` | `npm install @sociallane/widget-services` |
|
|
90
107
|
| simple-page-hero | `@sociallane/widget-simple-page-hero` | `npm install @sociallane/widget-simple-page-hero` |
|
|
91
108
|
| social-proof | `@sociallane/widget-social-proof` | `npm install @sociallane/widget-social-proof` |
|
|
109
|
+
| social-proof-trust | `@sociallane/widget-social-proof-trust` | `npm install @sociallane/widget-social-proof-trust` |
|
|
92
110
|
| testimonial-quote | `@sociallane/widget-testimonial-quote` | `npm install @sociallane/widget-testimonial-quote` |
|
|
111
|
+
| widget-filter | `@sociallane/widget-widget-filter` | `npm install @sociallane/widget-widget-filter` |
|
|
93
112
|
|
|
94
113
|
Then add the slug to `widgets.json`.
|
|
95
114
|
|
|
@@ -99,12 +118,12 @@ Then add the slug to `widgets.json`.
|
|
|
99
118
|
|
|
100
119
|
| Category | Slugs |
|
|
101
120
|
|----------|-------|
|
|
102
|
-
| Heroes | `hero-split`, `hero-overlay`, `hero-saas`, `hero-collage`, `hero-centered-image`, `hero-stacked-image`, `hero-announcement`, `simple-page-hero` |
|
|
103
|
-
| Content | `content-block`, `intro-text`, `intro-pattern`, `faq`, `feature-list`, `feature-list-cta`, `feature-grid` |
|
|
104
|
-
| Cards & Grids | `card-hover-reveal`, `bento-grid`, `bento-portfolio`, `grid-
|
|
105
|
-
| Forms & CTAs | `cta-banner`, `cta-split`, `cta-notify`, `newsletter`, `form-contact`, `pricing-table` |
|
|
121
|
+
| Heroes | `hero-split`, `hero-overlay`, `hero-overlay-single`, `hero-overlay-slider`, `hero-saas-split`, `hero-saas-stacked`, `hero-saas-centered`, `hero-collage`, `hero-centered-image`, `hero-stacked-image`, `hero-announcement`, `simple-page-hero`, `page-hero-left`, `page-hero-center` |
|
|
122
|
+
| Content | `content-block`, `intro-text`, `intro-pattern`, `faq-stacked`, `faq-split`, `faq-centered`, `feature-list`, `feature-list-cta`, `feature-grid` |
|
|
123
|
+
| Cards & Grids | `card-hover-reveal`, `bento-grid`, `bento-portfolio`, `posts-grid`, `posts-grid-overlay`, `grid-team`, `testimonials-grid`, `testimonials-masonry`, `testimonials-bento`, `grid-case-studies`, `grid-components`, `logo-grid-centered`, `logo-grid-row`, `logo-grid-split`, `client-logos` |
|
|
124
|
+
| Forms & CTAs | `cta-banner`, `cta-split`, `cta-notify`, `newsletter`, `newsletter-card`, `newsletter-section`, `form-contact`, `pricing-table` |
|
|
106
125
|
| Navigation | `nav-default`, `nav-centered`, `nav-minimal`, `nav-compact`, `nav-floating`, `footer`, `footer-brand`, `footer-links-contact` |
|
|
107
|
-
| Other | `section-stats`, `social-proof`, `services`, `blog-grid`, `outreach-dashboard`, `pipeline-dashboard`, `sales-dashboard`, `testimonial-quote` |
|
|
126
|
+
| Other | `section-stats`, `social-proof`, `social-proof-trust`, `services`, `blog-grid`, `outreach-dashboard`, `pipeline-dashboard`, `sales-dashboard`, `testimonial-quote`, `widget-filter` |
|
|
108
127
|
|
|
109
128
|
---
|
|
110
129
|
|
|
@@ -29,7 +29,8 @@ Edit `widgets.json` to include only the widget slugs you want. You can also let
|
|
|
29
29
|
|
|
30
30
|
Adding or removing widget directories is reflected in `widgets.json` automatically:
|
|
31
31
|
|
|
32
|
-
- **On `npm install`** — The postinstall script runs `sync-widgets` then `build
|
|
32
|
+
- **On `npm install`** — The postinstall script runs `sync-widgets` then `build` by default. Any new folder under `packages/widgets/{slug}` with `{slug}.php` is added to `widgets.json`; removed folders are removed from the list. Existing order is preserved; new slugs are appended sorted.
|
|
33
|
+
The installers use `SOCIALLANE_SKIP_SYNC_WIDGETS=1` for base/cherry-pick flows so `widgets.json` is not expanded unintentionally.
|
|
33
34
|
- **Manual sync** — From the plugin root run:
|
|
34
35
|
```bash
|
|
35
36
|
npm run sync-widgets
|
|
@@ -42,7 +43,7 @@ Adding or removing widget directories is reflected in `widgets.json` automatical
|
|
|
42
43
|
"hero-split",
|
|
43
44
|
"hero-overlay",
|
|
44
45
|
"content-block",
|
|
45
|
-
"faq"
|
|
46
|
+
"faq-stacked"
|
|
46
47
|
]
|
|
47
48
|
}
|
|
48
49
|
```
|
|
@@ -65,10 +66,10 @@ Use submodules so each WordPress instance only has the core package and the widg
|
|
|
65
66
|
|
|
66
67
|
# Add only the widgets you want
|
|
67
68
|
git submodule add <url-to-widget-hero-split> packages/widgets/hero-split
|
|
68
|
-
git submodule add <url-to-widget-faq> packages/widgets/faq
|
|
69
|
+
git submodule add <url-to-widget-faq-stacked> packages/widgets/faq-stacked
|
|
69
70
|
```
|
|
70
71
|
|
|
71
|
-
3. Update **widgets.json** so its `widgets` array lists only the slugs you added (e.g. `hero-split`, `faq`).
|
|
72
|
+
3. Update **widgets.json** so its `widgets` array lists only the slugs you added (e.g. `hero-split`, `faq-stacked`).
|
|
72
73
|
|
|
73
74
|
4. Install and build from plugin root (both required for styled widgets):
|
|
74
75
|
|
|
@@ -123,13 +124,13 @@ The plugin is published as `@sociallane/elements`. To publish:
|
|
|
123
124
|
|
|
124
125
|
## Per-widget npm packages
|
|
125
126
|
|
|
126
|
-
Individual widgets are published as `@sociallane/widget-<slug>` (
|
|
127
|
+
Individual widgets are published as `@sociallane/widget-<slug>` (for example `@sociallane/widget-faq-stacked`). Run from your WordPress root or `wp-content/plugins`:
|
|
127
128
|
|
|
128
129
|
```bash
|
|
129
|
-
npx @sociallane/widget-
|
|
130
|
+
npx @sociallane/widget-faq-stacked
|
|
130
131
|
```
|
|
131
132
|
|
|
132
|
-
The installer installs the base plugin (`@sociallane/elements`) with `--
|
|
133
|
+
The installer installs the base plugin (`@sociallane/elements`) with `--base` if it is not present, then delegates to `npx @sociallane/elements add --target <pluginDir> <slug>`. Use these when you want a one-command install for a single widget. To add multiple widgets, `npx @sociallane/elements add --target <pluginDir> slug1 slug2` is usually simpler.
|
|
133
134
|
|
|
134
135
|
## Adding a new widget package
|
|
135
136
|
|
package/package.json
CHANGED
|
@@ -484,8 +484,8 @@ function prepare_widget_filter_view( array $settings, string $widget_id ): array
|
|
|
484
484
|
// Grid columns class
|
|
485
485
|
$grid_columns = [
|
|
486
486
|
'2' => 'grid-cols-1 sm:grid-cols-2',
|
|
487
|
-
'3' => 'grid-cols-1 sm:grid-cols-2
|
|
488
|
-
'4' => 'grid-cols-1 sm:grid-cols-2
|
|
487
|
+
'3' => 'grid-cols-1 sm:grid-cols-2 md:grid-cols-3',
|
|
488
|
+
'4' => 'grid-cols-1 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4',
|
|
489
489
|
];
|
|
490
490
|
$grid_class = $grid_columns[ $columns ] ?? $grid_columns['3'];
|
|
491
491
|
|
package/scripts/install.js
CHANGED
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* SocialLane Elements CLI
|
|
4
4
|
*
|
|
5
|
+
* Install (base): npx @sociallane/elements --base [path]
|
|
5
6
|
* Install (full): npx @sociallane/elements [path]
|
|
6
7
|
* Add widgets: npx @sociallane/elements add <slug> [slug...]
|
|
7
8
|
*
|
|
8
9
|
* Install: copies package to wp-content/plugins/sociallane-elements (or path), runs npm install.
|
|
10
|
+
* Base install: installs core/deps and keeps widgets.json empty (no widgets loaded by default).
|
|
9
11
|
* Add: copies selected widget folders into an existing plugin, updates widgets.json, runs npm install.
|
|
10
12
|
*/
|
|
11
13
|
|
|
@@ -16,9 +18,44 @@ import { fileURLToPath } from 'url';
|
|
|
16
18
|
|
|
17
19
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
18
20
|
const packageRoot = path.resolve(__dirname, '..');
|
|
19
|
-
const
|
|
21
|
+
const packageJsonPath = path.join(packageRoot, 'package.json');
|
|
22
|
+
|
|
23
|
+
function getCliVersion() {
|
|
24
|
+
try {
|
|
25
|
+
const pkg = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
|
26
|
+
return typeof pkg.version === 'string' ? pkg.version : '0.0.0';
|
|
27
|
+
} catch {
|
|
28
|
+
return '0.0.0';
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function printHelp() {
|
|
33
|
+
console.log('SocialLane Elements CLI');
|
|
34
|
+
console.log('');
|
|
35
|
+
console.log('Usage:');
|
|
36
|
+
console.log(' npx @sociallane/elements [--base|--minimal] [target]');
|
|
37
|
+
console.log(' npx @sociallane/elements add [--only] [--target <path>] <slug> [slug...]');
|
|
38
|
+
console.log(' npx @sociallane/elements --help');
|
|
39
|
+
console.log(' npx @sociallane/elements --version');
|
|
40
|
+
console.log('');
|
|
41
|
+
console.log('Options:');
|
|
42
|
+
console.log(' --base, --minimal Install core/deps only, keep widgets.json empty');
|
|
43
|
+
console.log(' --only With add: replace widgets.json with exactly provided slugs');
|
|
44
|
+
console.log(' --target <path> With add: explicit plugin directory target');
|
|
45
|
+
console.log(' --help Show this help text');
|
|
46
|
+
console.log(' --version Show CLI version');
|
|
47
|
+
console.log('');
|
|
48
|
+
console.log('Examples:');
|
|
49
|
+
console.log(' npx @sociallane/elements --base');
|
|
50
|
+
console.log(' npx @sociallane/elements add faq-stacked hero-split');
|
|
51
|
+
console.log(' npx @sociallane/elements add --only --target wp-content/plugins/sociallane-elements content-block');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function resolvePluginDir(targetPath = '') {
|
|
55
|
+
if (targetPath) {
|
|
56
|
+
return path.resolve(process.cwd(), targetPath);
|
|
57
|
+
}
|
|
20
58
|
|
|
21
|
-
function resolvePluginDir() {
|
|
22
59
|
const cwd = process.cwd();
|
|
23
60
|
const normalized = path.normalize(cwd);
|
|
24
61
|
const pluginsSegment = 'wp-content' + path.sep + 'plugins';
|
|
@@ -41,6 +78,26 @@ function resolvePluginDir() {
|
|
|
41
78
|
return path.join(cwd, 'wp-content', 'plugins', 'sociallane-elements');
|
|
42
79
|
}
|
|
43
80
|
|
|
81
|
+
function getWidgetsSourceDir() {
|
|
82
|
+
const candidates = [
|
|
83
|
+
path.join(packageRoot, 'packages', 'widgets'),
|
|
84
|
+
path.join(packageRoot, 'widgets'),
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
for (const dir of candidates) {
|
|
88
|
+
if (!existsSync(dir)) {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
const available = readdirSync(dir, { withFileTypes: true })
|
|
92
|
+
.filter((d) => d.isDirectory() && existsSync(path.join(dir, d.name, `${d.name}.php`)))
|
|
93
|
+
.map((d) => d.name);
|
|
94
|
+
if (available.length > 0) {
|
|
95
|
+
return dir;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return candidates[0];
|
|
99
|
+
}
|
|
100
|
+
|
|
44
101
|
function updateWidgetsJson(pluginDir, slugsToAdd, replaceAll = false) {
|
|
45
102
|
const widgetsJsonPath = path.join(pluginDir, 'widgets.json');
|
|
46
103
|
let existing = [];
|
|
@@ -71,8 +128,9 @@ function updateWidgetsJson(pluginDir, slugsToAdd, replaceAll = false) {
|
|
|
71
128
|
|
|
72
129
|
function addWidgets(slugs, options = {}) {
|
|
73
130
|
const replaceAll = options.replaceAll === true;
|
|
74
|
-
const pluginDir = resolvePluginDir();
|
|
131
|
+
const pluginDir = resolvePluginDir(options.targetPath || '');
|
|
75
132
|
const widgetsDest = path.join(pluginDir, 'packages', 'widgets');
|
|
133
|
+
const widgetsSource = getWidgetsSourceDir();
|
|
76
134
|
|
|
77
135
|
if (!existsSync(path.join(pluginDir, 'sociallane-elements.php'))) {
|
|
78
136
|
console.error('Plugin not found at', pluginDir);
|
|
@@ -85,8 +143,10 @@ function addWidgets(slugs, options = {}) {
|
|
|
85
143
|
process.exit(1);
|
|
86
144
|
}
|
|
87
145
|
|
|
146
|
+
console.log('Target plugin:', pluginDir);
|
|
147
|
+
|
|
88
148
|
const available = readdirSync(widgetsSource, { withFileTypes: true })
|
|
89
|
-
.filter((d) => d.isDirectory())
|
|
149
|
+
.filter((d) => d.isDirectory() && existsSync(path.join(widgetsSource, d.name, `${d.name}.php`)))
|
|
90
150
|
.map((d) => d.name);
|
|
91
151
|
|
|
92
152
|
const missing = slugs.filter((s) => !available.includes(s));
|
|
@@ -136,6 +196,14 @@ function addWidgets(slugs, options = {}) {
|
|
|
136
196
|
console.log('Done. Widgets added:', slugs.join(', '));
|
|
137
197
|
}
|
|
138
198
|
|
|
199
|
+
function prepareBaseMode(pluginDir) {
|
|
200
|
+
const widgetsDest = path.join(pluginDir, 'packages', 'widgets');
|
|
201
|
+
if (!existsSync(widgetsDest)) {
|
|
202
|
+
mkdirSync(widgetsDest, { recursive: true });
|
|
203
|
+
}
|
|
204
|
+
updateWidgetsJson(pluginDir, [], true);
|
|
205
|
+
}
|
|
206
|
+
|
|
139
207
|
function copyPackage(toDir, filter) {
|
|
140
208
|
if (!existsSync(toDir)) {
|
|
141
209
|
mkdirSync(toDir, { recursive: true });
|
|
@@ -182,12 +250,21 @@ function install(targetPath, minimal) {
|
|
|
182
250
|
const targetResolved = path.resolve(target);
|
|
183
251
|
const isSelf = targetResolved === path.resolve(packageRoot) || targetResolved.startsWith(packageRoot + path.sep);
|
|
184
252
|
|
|
185
|
-
console.log(
|
|
253
|
+
console.log(
|
|
254
|
+
'SocialLane Elements installer' +
|
|
255
|
+
(minimal ? ' (base mode – add widgets with: npx @sociallane/elements add <slug> ...)' : '')
|
|
256
|
+
);
|
|
186
257
|
console.log('Target:', target);
|
|
187
258
|
|
|
188
259
|
if (isSelf) {
|
|
260
|
+
if (minimal) {
|
|
261
|
+
prepareBaseMode(packageRoot);
|
|
262
|
+
}
|
|
189
263
|
console.log('Target is the current package. Running npm install here...');
|
|
190
264
|
} else if (existsSync(target) && existsSync(path.join(target, 'package.json'))) {
|
|
265
|
+
if (minimal) {
|
|
266
|
+
prepareBaseMode(target);
|
|
267
|
+
}
|
|
191
268
|
console.log('Target already exists. Running npm install only...');
|
|
192
269
|
} else {
|
|
193
270
|
console.log('Copying package...');
|
|
@@ -196,16 +273,18 @@ function install(targetPath, minimal) {
|
|
|
196
273
|
const rel = path.relative(packageRoot, src).split(path.sep).join('/');
|
|
197
274
|
// Exclude node_modules within the package (not in parent path)
|
|
198
275
|
if (rel.includes('node_modules')) return false;
|
|
199
|
-
//
|
|
276
|
+
// Base install should not ship widget sources; users add explicitly via `add`.
|
|
200
277
|
if (rel === 'packages/widgets' || rel.startsWith('packages/widgets/')) return false;
|
|
278
|
+
// Exclude legacy widgets directory and generated npm-widget package folders.
|
|
279
|
+
if (rel === 'widgets' || rel.startsWith('widgets/')) return false;
|
|
280
|
+
if (rel === 'packages/npm-widgets' || rel.startsWith('packages/npm-widgets/')) return false;
|
|
201
281
|
return true;
|
|
202
282
|
});
|
|
203
283
|
const widgetsDest = path.join(target, 'packages', 'widgets');
|
|
204
284
|
if (!existsSync(widgetsDest)) {
|
|
205
285
|
mkdirSync(widgetsDest, { recursive: true });
|
|
206
286
|
}
|
|
207
|
-
|
|
208
|
-
writeFileSync(widgetsJson, JSON.stringify({ widgets: [] }, null, 2));
|
|
287
|
+
updateWidgetsJson(target, [], true);
|
|
209
288
|
} else {
|
|
210
289
|
copyPackage(target);
|
|
211
290
|
}
|
|
@@ -214,8 +293,15 @@ function install(targetPath, minimal) {
|
|
|
214
293
|
const installDir = isSelf ? packageRoot : target;
|
|
215
294
|
console.log('Running npm install in', installDir + '...');
|
|
216
295
|
const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
296
|
+
const installEnv = {
|
|
297
|
+
...process.env,
|
|
298
|
+
};
|
|
299
|
+
if (minimal) {
|
|
300
|
+
installEnv.SOCIALLANE_SKIP_SYNC_WIDGETS = '1';
|
|
301
|
+
}
|
|
217
302
|
const result = spawnSync(npmCmd, ['install'], {
|
|
218
303
|
cwd: installDir,
|
|
304
|
+
env: installEnv,
|
|
219
305
|
stdio: 'inherit',
|
|
220
306
|
shell: true,
|
|
221
307
|
});
|
|
@@ -237,21 +323,72 @@ function install(targetPath, minimal) {
|
|
|
237
323
|
|
|
238
324
|
function main() {
|
|
239
325
|
const args = process.argv.slice(2);
|
|
240
|
-
const minimal = args.includes('--minimal');
|
|
241
|
-
const installArgs = args.filter((a) => a !== '--minimal');
|
|
242
326
|
|
|
243
|
-
if (
|
|
244
|
-
|
|
327
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
328
|
+
printHelp();
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (args.includes('--version') || args.includes('-v')) {
|
|
333
|
+
console.log(getCliVersion());
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
if (args[0] === 'add') {
|
|
338
|
+
const addArgs = args.slice(1).filter(Boolean);
|
|
339
|
+
const knownAddFlags = new Set(['--only', '--target']);
|
|
340
|
+
let targetPath = '';
|
|
341
|
+
const slugs = [];
|
|
342
|
+
for (let i = 0; i < addArgs.length; i++) {
|
|
343
|
+
const arg = addArgs[i];
|
|
344
|
+
if (arg === '--target') {
|
|
345
|
+
const next = addArgs[i + 1];
|
|
346
|
+
if (!next || next.startsWith('-')) {
|
|
347
|
+
console.error('Missing value for --target');
|
|
348
|
+
process.exit(1);
|
|
349
|
+
}
|
|
350
|
+
targetPath = next;
|
|
351
|
+
i++;
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
if (arg.startsWith('-')) {
|
|
355
|
+
if (!knownAddFlags.has(arg)) {
|
|
356
|
+
console.error('Unknown option for add:', arg);
|
|
357
|
+
process.exit(1);
|
|
358
|
+
}
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
slugs.push(arg);
|
|
362
|
+
}
|
|
363
|
+
|
|
245
364
|
const replaceAll = addArgs.includes('--only');
|
|
246
|
-
const slugs = addArgs.filter((arg) => arg !== '--only');
|
|
247
365
|
if (slugs.length === 0) {
|
|
248
366
|
console.error('Usage: npx @sociallane/elements add [--only] <slug> [slug...]');
|
|
249
367
|
console.error('Example: npx @sociallane/elements add --only hero-split faq-stacked content-block');
|
|
250
368
|
process.exit(1);
|
|
251
369
|
}
|
|
252
|
-
addWidgets(slugs, { replaceAll });
|
|
370
|
+
addWidgets(slugs, { replaceAll, targetPath });
|
|
253
371
|
} else {
|
|
254
|
-
|
|
372
|
+
let minimal = false;
|
|
373
|
+
const positionals = [];
|
|
374
|
+
for (const arg of args) {
|
|
375
|
+
if (arg === '--minimal' || arg === '--base') {
|
|
376
|
+
minimal = true;
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
if (arg.startsWith('-')) {
|
|
380
|
+
console.error('Unknown option:', arg);
|
|
381
|
+
process.exit(1);
|
|
382
|
+
}
|
|
383
|
+
positionals.push(arg);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
if (positionals.length > 1) {
|
|
387
|
+
console.error('Too many positional arguments. Expected at most one target path.');
|
|
388
|
+
process.exit(1);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
install(positionals[0], minimal);
|
|
255
392
|
}
|
|
256
393
|
}
|
|
257
394
|
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* Per-widget installer: run from a @sociallane/widget-<slug> package (npx).
|
|
4
|
-
* Ensures SocialLane Elements plugin is installed
|
|
5
|
-
*
|
|
4
|
+
* Ensures SocialLane Elements plugin is installed in base mode, then delegates
|
|
5
|
+
* widget import to the main CLI add command.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { existsSync, readFileSync } from 'fs';
|
|
9
9
|
import { spawnSync } from 'child_process';
|
|
10
10
|
import path from 'path';
|
|
11
11
|
import { fileURLToPath } from 'url';
|
|
12
12
|
|
|
13
13
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
14
14
|
const packageRoot = path.resolve(__dirname);
|
|
15
|
-
const widgetDir = path.join(packageRoot, 'widget');
|
|
16
15
|
|
|
17
16
|
function getSlugFromPackage() {
|
|
18
17
|
const pkgPath = path.join(packageRoot, 'package.json');
|
|
@@ -56,62 +55,29 @@ function resolvePluginDir() {
|
|
|
56
55
|
return path.join(cwd, 'wp-content', 'plugins', 'sociallane-elements');
|
|
57
56
|
}
|
|
58
57
|
|
|
59
|
-
function
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
if (
|
|
66
|
-
|
|
67
|
-
process.exit(1);
|
|
58
|
+
function runNpx(args, cwd) {
|
|
59
|
+
const r = spawnSync('npx', ['--yes', ...args], {
|
|
60
|
+
cwd,
|
|
61
|
+
stdio: 'inherit',
|
|
62
|
+
shell: true,
|
|
63
|
+
});
|
|
64
|
+
if (r.status !== 0) {
|
|
65
|
+
process.exit(r.status ?? 1);
|
|
68
66
|
}
|
|
67
|
+
}
|
|
69
68
|
|
|
69
|
+
function main() {
|
|
70
|
+
const slug = getSlugFromPackage();
|
|
70
71
|
const pluginDir = resolvePluginDir();
|
|
71
|
-
const widgetsDest = path.join(pluginDir, 'packages', 'widgets');
|
|
72
72
|
const pluginExists = existsSync(path.join(pluginDir, 'sociallane-elements.php'));
|
|
73
73
|
|
|
74
74
|
if (!pluginExists) {
|
|
75
75
|
console.log('SocialLane Elements not found. Installing base plugin...');
|
|
76
|
-
|
|
77
|
-
cwd: path.dirname(pluginDir),
|
|
78
|
-
stdio: 'inherit',
|
|
79
|
-
shell: true,
|
|
80
|
-
});
|
|
81
|
-
if (r.status !== 0) {
|
|
82
|
-
process.exit(r.status ?? 1);
|
|
83
|
-
}
|
|
76
|
+
runNpx(['@sociallane/elements', '--base', pluginDir], path.dirname(pluginDir));
|
|
84
77
|
}
|
|
85
78
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const dest = path.join(widgetsDest, slug);
|
|
91
|
-
cpSync(widgetDir, dest, { recursive: true, force: true });
|
|
92
|
-
console.log('Added widget:', slug);
|
|
93
|
-
|
|
94
|
-
console.log('Updating widgets.json and building...');
|
|
95
|
-
const syncResult = spawnSync('node', [path.join(pluginDir, 'scripts', 'sync-widgets.js')], {
|
|
96
|
-
cwd: pluginDir,
|
|
97
|
-
stdio: 'inherit',
|
|
98
|
-
});
|
|
99
|
-
if (syncResult.status !== 0) {
|
|
100
|
-
process.exit(syncResult.status ?? 1);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
104
|
-
const installResult = spawnSync(npmCmd, ['install'], {
|
|
105
|
-
cwd: pluginDir,
|
|
106
|
-
stdio: 'inherit',
|
|
107
|
-
shell: true,
|
|
108
|
-
});
|
|
109
|
-
if (installResult.status !== 0) {
|
|
110
|
-
if (installResult.error) {
|
|
111
|
-
console.error('Failed to run npm:', installResult.error.message);
|
|
112
|
-
}
|
|
113
|
-
process.exit(installResult.status ?? 1);
|
|
114
|
-
}
|
|
79
|
+
console.log('Adding widget:', slug);
|
|
80
|
+
runNpx(['@sociallane/elements', 'add', '--target', pluginDir, slug], path.dirname(pluginDir));
|
|
115
81
|
|
|
116
82
|
console.log('');
|
|
117
83
|
console.log('Done. Widget', slug, 'installed. Activate the plugin in WordPress → Plugins if needed.');
|