@sociallane/elements 1.0.7 → 1.0.8
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.
|
@@ -81,6 +81,18 @@ npx @sociallane/elements --minimal path/to/wp-content/plugins/sociallane-element
|
|
|
81
81
|
npx @sociallane/elements add hero-split faq # run from WordPress root or plugin dir
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
+
**Single widget (per-widget packages):**
|
|
85
|
+
|
|
86
|
+
You can install one widget at a time via its own package. This installs the SocialLane Elements plugin if needed, then adds that widget and builds:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# From your WordPress root or wp-content/plugins
|
|
90
|
+
npx @sociallane/widget-hero-overlay
|
|
91
|
+
npx @sociallane/widget-faq-stacked
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Each package is published as `@sociallane/widget-<slug>`. Use this when you only need one or two widgets and want a single command per widget.
|
|
95
|
+
|
|
84
96
|
---
|
|
85
97
|
|
|
86
98
|
## Post-install
|
|
@@ -121,6 +121,16 @@ The plugin is published as `@sociallane/elements`. To publish:
|
|
|
121
121
|
|
|
122
122
|
`.npmignore` excludes `node_modules`, `.git`, and dev files so the tarball contains plugin source and `packages/`. Consumers run `npm install` in the plugin directory after copying to `wp-content/plugins` to install workspaces and trigger the build.
|
|
123
123
|
|
|
124
|
+
## Per-widget npm packages
|
|
125
|
+
|
|
126
|
+
Individual widgets are published as `@sociallane/widget-<slug>` (e.g. `@sociallane/widget-hero-overlay`). Run from your WordPress root or `wp-content/plugins`:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
npx @sociallane/widget-hero-overlay
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The installer installs the base plugin (`@sociallane/elements`) with `--minimal` if it is not present, then copies the widget into the plugin, runs `sync-widgets`, and `npm install`. Use these when you want a one-command install for a single widget. To add multiple widgets, `npx @sociallane/elements add slug1 slug2` is usually simpler.
|
|
133
|
+
|
|
124
134
|
## Adding a new widget package
|
|
125
135
|
|
|
126
136
|
1. Add the widget directory under `packages/widgets/{slug}` with `{slug}.php`, `data/`, `templates/`, and `package.json` (see existing widgets).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sociallane/elements",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "Elementor widgets and elements with Tailwind CSS for SocialLane. WordPress plugin.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -30,6 +30,8 @@
|
|
|
30
30
|
"postinstall": "node scripts/postinstall.js",
|
|
31
31
|
"setup": "bash scripts/setup.sh",
|
|
32
32
|
"sync-widgets": "node scripts/sync-widgets.js",
|
|
33
|
+
"build:widget-packages": "node scripts/build-widget-packages.js",
|
|
34
|
+
"publish:widgets": "node scripts/build-widget-packages.js && node scripts/publish-widget-packages.js",
|
|
33
35
|
"reinstall": "rm -rf node_modules && npm install",
|
|
34
36
|
"format": "prettier --write .",
|
|
35
37
|
"format:check": "prettier --check ."
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Build per-widget npm packages under packages/npm-widgets/<slug>.
|
|
4
|
+
* Each package contains: package.json, widget/ (copy of packages/widgets/<slug>), install.js, README.md.
|
|
5
|
+
* Run from plugin root: npm run build:widget-packages
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
|
|
12
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
const pluginRoot = path.resolve(__dirname, '..');
|
|
14
|
+
const widgetsDir = path.join(pluginRoot, 'packages', 'widgets');
|
|
15
|
+
const npmWidgetsDir = path.join(pluginRoot, 'packages', 'npm-widgets');
|
|
16
|
+
|
|
17
|
+
function getWidgetSlugs() {
|
|
18
|
+
if (!existsSync(widgetsDir)) return [];
|
|
19
|
+
const entries = readdirSync(widgetsDir, { withFileTypes: true });
|
|
20
|
+
const slugs = [];
|
|
21
|
+
for (const ent of entries) {
|
|
22
|
+
if (!ent.isDirectory()) continue;
|
|
23
|
+
const slug = ent.name;
|
|
24
|
+
const phpFile = path.join(widgetsDir, slug, `${slug}.php`);
|
|
25
|
+
if (existsSync(phpFile)) slugs.push(slug);
|
|
26
|
+
}
|
|
27
|
+
return slugs.sort((a, b) => a.localeCompare(b));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function getRootVersion() {
|
|
31
|
+
const pkgPath = path.join(pluginRoot, 'package.json');
|
|
32
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
|
|
33
|
+
return pkg.version || '1.0.0';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function buildPackage(slug, version) {
|
|
37
|
+
const pkgDir = path.join(npmWidgetsDir, slug);
|
|
38
|
+
mkdirSync(pkgDir, { recursive: true });
|
|
39
|
+
|
|
40
|
+
const widgetSrc = path.join(widgetsDir, slug);
|
|
41
|
+
const widgetDest = path.join(pkgDir, 'widget');
|
|
42
|
+
cpSync(widgetSrc, widgetDest, { recursive: true, force: true });
|
|
43
|
+
|
|
44
|
+
const packageName = `@sociallane/widget-${slug}`;
|
|
45
|
+
const binName = `widget-${slug}`;
|
|
46
|
+
const packageJson = {
|
|
47
|
+
name: packageName,
|
|
48
|
+
version,
|
|
49
|
+
description: `SocialLane Elements widget: ${slug}. Install into WordPress plugin via npx.`,
|
|
50
|
+
type: 'module',
|
|
51
|
+
private: false,
|
|
52
|
+
bin: { [binName]: 'install.js' },
|
|
53
|
+
keywords: ['wordpress', 'elementor', 'widget', 'sociallane', slug],
|
|
54
|
+
repository: {
|
|
55
|
+
type: 'git',
|
|
56
|
+
url: 'git+https://github.com/Mitch00llK/sociallane-elements.git',
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
writeFileSync(path.join(pkgDir, 'package.json'), JSON.stringify(packageJson, null, 2) + '\n');
|
|
60
|
+
|
|
61
|
+
const readme = `# @sociallane/widget-${slug}
|
|
62
|
+
|
|
63
|
+
Elementor widget **${slug}** for SocialLane Elements.
|
|
64
|
+
|
|
65
|
+
## Install
|
|
66
|
+
|
|
67
|
+
From your WordPress root (or \`wp-content/plugins\`):
|
|
68
|
+
|
|
69
|
+
\`\`\`bash
|
|
70
|
+
npx @sociallane/widget-${slug}
|
|
71
|
+
\`\`\`
|
|
72
|
+
|
|
73
|
+
This installs the SocialLane Elements plugin if needed, then adds this widget and builds.
|
|
74
|
+
`;
|
|
75
|
+
writeFileSync(path.join(pkgDir, 'README.md'), readme);
|
|
76
|
+
|
|
77
|
+
const installerSrc = path.join(pluginRoot, 'scripts', 'widget-installer.js');
|
|
78
|
+
cpSync(installerSrc, path.join(pkgDir, 'install.js'), { force: true });
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function main() {
|
|
82
|
+
const slugs = getWidgetSlugs();
|
|
83
|
+
const version = getRootVersion();
|
|
84
|
+
if (!existsSync(npmWidgetsDir)) mkdirSync(npmWidgetsDir, { recursive: true });
|
|
85
|
+
for (const slug of slugs) {
|
|
86
|
+
buildPackage(slug, version);
|
|
87
|
+
console.log('Built:', `@sociallane/widget-${slug}`);
|
|
88
|
+
}
|
|
89
|
+
console.log('Done. Widget packages in packages/npm-widgets/');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
main();
|
package/scripts/install.js
CHANGED
|
@@ -20,8 +20,25 @@ const widgetsSource = path.join(packageRoot, 'packages', 'widgets');
|
|
|
20
20
|
|
|
21
21
|
function resolvePluginDir() {
|
|
22
22
|
const cwd = process.cwd();
|
|
23
|
-
const
|
|
24
|
-
|
|
23
|
+
const normalized = path.normalize(cwd);
|
|
24
|
+
const pluginsSegment = 'wp-content' + path.sep + 'plugins';
|
|
25
|
+
if (existsSync(path.join(cwd, 'sociallane-elements.php')) && existsSync(path.join(cwd, 'packages', 'widgets'))) {
|
|
26
|
+
return cwd;
|
|
27
|
+
}
|
|
28
|
+
if (normalized.endsWith(pluginsSegment) || normalized.endsWith(pluginsSegment + path.sep)) {
|
|
29
|
+
return path.join(cwd, 'sociallane-elements');
|
|
30
|
+
}
|
|
31
|
+
if (normalized.includes(pluginsSegment + path.sep)) {
|
|
32
|
+
const idx = normalized.indexOf(pluginsSegment);
|
|
33
|
+
return path.join(normalized.slice(0, idx + pluginsSegment.length), 'sociallane-elements');
|
|
34
|
+
}
|
|
35
|
+
if (path.basename(cwd) === 'wp-content') {
|
|
36
|
+
return path.join(cwd, 'plugins', 'sociallane-elements');
|
|
37
|
+
}
|
|
38
|
+
if (existsSync(path.join(cwd, 'wp-content', 'plugins'))) {
|
|
39
|
+
return path.join(cwd, 'wp-content', 'plugins', 'sociallane-elements');
|
|
40
|
+
}
|
|
41
|
+
return path.join(cwd, 'wp-content', 'plugins', 'sociallane-elements');
|
|
25
42
|
}
|
|
26
43
|
|
|
27
44
|
function addWidgets(slugs) {
|
|
@@ -109,9 +126,18 @@ function copyPackage(toDir, filter) {
|
|
|
109
126
|
function install(targetPath, minimal) {
|
|
110
127
|
const cwd = process.cwd();
|
|
111
128
|
const resolveDefaultTarget = () => {
|
|
129
|
+
const normalized = path.normalize(cwd);
|
|
130
|
+
const pluginsSegment = 'wp-content' + path.sep + 'plugins';
|
|
112
131
|
if (existsSync(path.join(cwd, 'sociallane-elements.php'))) {
|
|
113
132
|
return cwd;
|
|
114
133
|
}
|
|
134
|
+
if (normalized.endsWith(pluginsSegment) || normalized.endsWith(pluginsSegment + path.sep)) {
|
|
135
|
+
return path.join(cwd, 'sociallane-elements');
|
|
136
|
+
}
|
|
137
|
+
if (normalized.includes(pluginsSegment + path.sep)) {
|
|
138
|
+
const idx = normalized.indexOf(pluginsSegment);
|
|
139
|
+
return path.join(normalized.slice(0, idx + pluginsSegment.length), 'sociallane-elements');
|
|
140
|
+
}
|
|
115
141
|
if (path.basename(cwd) === 'plugins' && path.basename(path.dirname(cwd)) === 'wp-content') {
|
|
116
142
|
return path.join(cwd, 'sociallane-elements');
|
|
117
143
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Publish all per-widget packages under packages/npm-widgets/.
|
|
4
|
+
* Run from plugin root: npm run publish:widgets
|
|
5
|
+
* (build:widget-packages is run first by the npm script.)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { readdirSync, existsSync } from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
import { spawnSync } from 'child_process';
|
|
12
|
+
|
|
13
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const pluginRoot = path.resolve(__dirname, '..');
|
|
15
|
+
const npmWidgetsDir = path.join(pluginRoot, 'packages', 'npm-widgets');
|
|
16
|
+
|
|
17
|
+
if (!existsSync(npmWidgetsDir)) {
|
|
18
|
+
console.error('packages/npm-widgets/ not found. Run npm run build:widget-packages first.');
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const dirs = readdirSync(npmWidgetsDir, { withFileTypes: true })
|
|
23
|
+
.filter((d) => d.isDirectory())
|
|
24
|
+
.map((d) => d.name)
|
|
25
|
+
.sort((a, b) => a.localeCompare(b));
|
|
26
|
+
|
|
27
|
+
if (dirs.length === 0) {
|
|
28
|
+
console.error('No widget packages in packages/npm-widgets/');
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
33
|
+
(async () => {
|
|
34
|
+
for (let i = 0; i < dirs.length; i++) {
|
|
35
|
+
const slug = dirs[i];
|
|
36
|
+
const pkgDir = path.join(npmWidgetsDir, slug);
|
|
37
|
+
if (!existsSync(path.join(pkgDir, 'package.json'))) continue;
|
|
38
|
+
console.log('Publishing @sociallane/widget-' + slug + '...');
|
|
39
|
+
const r = spawnSync(npmCmd, ['publish', '--access', 'public'], {
|
|
40
|
+
cwd: pkgDir,
|
|
41
|
+
stdio: 'inherit',
|
|
42
|
+
shell: true,
|
|
43
|
+
});
|
|
44
|
+
if (r.status !== 0) {
|
|
45
|
+
process.exit(r.status ?? 1);
|
|
46
|
+
}
|
|
47
|
+
if (i < dirs.length - 1) {
|
|
48
|
+
await new Promise((r) => setTimeout(r, 2000));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
console.log('Done. Published', dirs.length, 'widget packages.');
|
|
52
|
+
})();
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Per-widget installer: run from a @sociallane/widget-<slug> package (npx).
|
|
4
|
+
* Ensures SocialLane Elements plugin is installed, then copies this package's widget/
|
|
5
|
+
* into the plugin's packages/widgets/<slug>, runs sync-widgets and npm install.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { cpSync, existsSync, mkdirSync, readFileSync } from 'fs';
|
|
9
|
+
import { spawnSync } from 'child_process';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
import { fileURLToPath } from 'url';
|
|
12
|
+
|
|
13
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const packageRoot = path.resolve(__dirname);
|
|
15
|
+
const widgetDir = path.join(packageRoot, 'widget');
|
|
16
|
+
|
|
17
|
+
function getSlugFromPackage() {
|
|
18
|
+
const pkgPath = path.join(packageRoot, 'package.json');
|
|
19
|
+
if (!existsSync(pkgPath)) {
|
|
20
|
+
console.error('package.json not found in', packageRoot);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
|
|
24
|
+
const name = pkg.name || '';
|
|
25
|
+
const match = name.match(/^@sociallane\/widget-(.+)$/);
|
|
26
|
+
if (!match) {
|
|
27
|
+
console.error('Package name must be @sociallane/widget-<slug>. Got:', name);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
return match[1];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function resolvePluginDir() {
|
|
34
|
+
const cwd = process.cwd();
|
|
35
|
+
const normalized = path.normalize(cwd);
|
|
36
|
+
const pluginsSegment = 'wp-content' + path.sep + 'plugins';
|
|
37
|
+
if (existsSync(path.join(cwd, 'sociallane-elements.php')) && existsSync(path.join(cwd, 'packages', 'widgets'))) {
|
|
38
|
+
return cwd;
|
|
39
|
+
}
|
|
40
|
+
if (normalized.endsWith(pluginsSegment) || normalized.endsWith(pluginsSegment + path.sep)) {
|
|
41
|
+
return path.join(cwd, 'sociallane-elements');
|
|
42
|
+
}
|
|
43
|
+
if (normalized.includes(pluginsSegment + path.sep)) {
|
|
44
|
+
const idx = normalized.indexOf(pluginsSegment);
|
|
45
|
+
return path.join(normalized.slice(0, idx + pluginsSegment.length), 'sociallane-elements');
|
|
46
|
+
}
|
|
47
|
+
if (path.basename(cwd) === 'plugins' && path.basename(path.dirname(cwd)) === 'wp-content') {
|
|
48
|
+
return path.join(cwd, 'sociallane-elements');
|
|
49
|
+
}
|
|
50
|
+
if (path.basename(cwd) === 'wp-content') {
|
|
51
|
+
return path.join(cwd, 'plugins', 'sociallane-elements');
|
|
52
|
+
}
|
|
53
|
+
if (existsSync(path.join(cwd, 'wp-content', 'plugins'))) {
|
|
54
|
+
return path.join(cwd, 'wp-content', 'plugins', 'sociallane-elements');
|
|
55
|
+
}
|
|
56
|
+
return path.join(cwd, 'wp-content', 'plugins', 'sociallane-elements');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function main() {
|
|
60
|
+
const slug = getSlugFromPackage();
|
|
61
|
+
if (!existsSync(widgetDir)) {
|
|
62
|
+
console.error('Widget folder not found:', widgetDir);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
if (!existsSync(path.join(widgetDir, `${slug}.php`))) {
|
|
66
|
+
console.error('Invalid widget: missing', path.join(widgetDir, `${slug}.php`));
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const pluginDir = resolvePluginDir();
|
|
71
|
+
const widgetsDest = path.join(pluginDir, 'packages', 'widgets');
|
|
72
|
+
const pluginExists = existsSync(path.join(pluginDir, 'sociallane-elements.php'));
|
|
73
|
+
|
|
74
|
+
if (!pluginExists) {
|
|
75
|
+
console.log('SocialLane Elements not found. Installing base plugin...');
|
|
76
|
+
const r = spawnSync('npx', ['--yes', '@sociallane/elements', '--minimal'], {
|
|
77
|
+
cwd: path.dirname(pluginDir),
|
|
78
|
+
stdio: 'inherit',
|
|
79
|
+
shell: true,
|
|
80
|
+
});
|
|
81
|
+
if (r.status !== 0) {
|
|
82
|
+
process.exit(r.status ?? 1);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (!existsSync(widgetsDest)) {
|
|
87
|
+
mkdirSync(widgetsDest, { recursive: true });
|
|
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
|
+
}
|
|
115
|
+
|
|
116
|
+
console.log('');
|
|
117
|
+
console.log('Done. Widget', slug, 'installed. Activate the plugin in WordPress → Plugins if needed.');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
try {
|
|
121
|
+
main();
|
|
122
|
+
} catch (err) {
|
|
123
|
+
console.error('Widget installer failed:', err.message);
|
|
124
|
+
if (process.env.DEBUG) {
|
|
125
|
+
console.error(err.stack);
|
|
126
|
+
}
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|