@loopress/cli 0.6.0 → 0.8.0
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 +98 -117
- package/dist/commands/composer/pull.js +5 -15
- package/dist/commands/composer/push.js +8 -17
- package/dist/commands/init.js +15 -6
- package/dist/commands/login.js +2 -2
- package/dist/commands/logout.js +2 -2
- package/dist/commands/plugin/add.d.ts +0 -2
- package/dist/commands/plugin/add.js +11 -32
- package/dist/commands/plugin/pull.js +8 -19
- package/dist/commands/plugin/push.d.ts +1 -0
- package/dist/commands/plugin/push.js +23 -48
- package/dist/commands/project/config.d.ts +1 -0
- package/dist/commands/project/config.js +36 -17
- package/dist/commands/project/list.js +4 -5
- package/dist/commands/project/remove.js +33 -14
- package/dist/commands/project/switch.d.ts +2 -0
- package/dist/commands/project/switch.js +28 -9
- package/dist/commands/snippet/list.d.ts +1 -1
- package/dist/commands/snippet/list.js +26 -41
- package/dist/commands/snippet/pull.d.ts +1 -1
- package/dist/commands/snippet/pull.js +45 -53
- package/dist/commands/snippet/push.d.ts +2 -2
- package/dist/commands/snippet/push.js +112 -68
- package/dist/commands/{project/remove-env.d.ts → status.d.ts} +3 -1
- package/dist/commands/status.js +66 -0
- package/dist/config/auth.manager.d.ts +0 -2
- package/dist/config/auth.manager.js +5 -25
- package/dist/config/json-file.d.ts +2 -0
- package/dist/config/json-file.js +21 -0
- package/dist/config/project-config.manager.d.ts +18 -13
- package/dist/config/project-config.manager.js +90 -59
- package/dist/lib/base.d.ts +14 -4
- package/dist/lib/base.js +69 -29
- package/dist/lib/push-command.d.ts +0 -1
- package/dist/lib/push-command.js +0 -1
- package/dist/lib/wp-client.d.ts +15 -0
- package/dist/lib/wp-client.js +53 -0
- package/dist/{config/types.d.ts → types/config.d.ts} +5 -2
- package/dist/types/snippet.d.ts +8 -0
- package/dist/utils/loopress-config.js +5 -2
- package/dist/utils/snippet-plugin-flag.d.ts +3 -0
- package/dist/utils/snippet-plugin-flag.js +8 -0
- package/dist/utils/snippet-plugin.d.ts +24 -2
- package/dist/utils/snippet-plugin.js +170 -14
- package/oclif.manifest.json +122 -108
- package/package.json +21 -4
- package/dist/commands/project/remove-env.js +0 -33
- package/dist/commands/project/switch-env.d.ts +0 -6
- package/dist/commands/project/switch-env.js +0 -33
- package/dist/types/menu.d.ts +0 -7
- package/dist/types/menu.js +0 -1
- /package/dist/{config/types.js → types/config.js} +0 -0
|
@@ -1,8 +1,32 @@
|
|
|
1
|
-
function parseType(raw) {
|
|
1
|
+
export function parseType(raw) {
|
|
2
2
|
const valid = ['css', 'html', 'js', 'php', 'text'];
|
|
3
3
|
const value = String(raw ?? '').toLowerCase();
|
|
4
4
|
return valid.includes(value) ? value : null;
|
|
5
5
|
}
|
|
6
|
+
const VALID_LOCATIONS = new Set(['admin', 'body', 'everywhere', 'footer', 'frontend', 'header', 'once']);
|
|
7
|
+
export function parseLocation(raw) {
|
|
8
|
+
const value = String(raw ?? '').toLowerCase();
|
|
9
|
+
return VALID_LOCATIONS.has(value) ? value : null;
|
|
10
|
+
}
|
|
11
|
+
export function parseInsertMethod(raw) {
|
|
12
|
+
return raw === 'auto' || raw === 'shortcode' ? raw : null;
|
|
13
|
+
}
|
|
14
|
+
// The sensible default placement for a freshly pushed snippet that doesn't specify a location.
|
|
15
|
+
export function defaultLocationForType(type) {
|
|
16
|
+
switch (type) {
|
|
17
|
+
case 'css': {
|
|
18
|
+
return 'header';
|
|
19
|
+
}
|
|
20
|
+
case 'html':
|
|
21
|
+
case 'js':
|
|
22
|
+
case 'text': {
|
|
23
|
+
return 'footer';
|
|
24
|
+
}
|
|
25
|
+
case 'php': {
|
|
26
|
+
return 'everywhere';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
6
30
|
function inferTypeFromCode(code) {
|
|
7
31
|
const firstLine = code.trimStart().split('\n')[0].trimStart();
|
|
8
32
|
if (firstLine.startsWith('<?'))
|
|
@@ -14,52 +38,184 @@ function inferTypeFromCode(code) {
|
|
|
14
38
|
function resolveType(raw, code) {
|
|
15
39
|
return parseType(raw) ?? inferTypeFromCode(code);
|
|
16
40
|
}
|
|
41
|
+
function resolvePriority(raw) {
|
|
42
|
+
const value = Number(raw);
|
|
43
|
+
return Number.isFinite(value) ? value : 10;
|
|
44
|
+
}
|
|
45
|
+
// Snippet files on disk keep the <?php opening tag so they're valid, syntax-highlighted PHP files.
|
|
46
|
+
// Both plugins store just the executable body, so it's stripped before push and restored on pull
|
|
47
|
+
// (see buildSnippetFile in commands/snippet/pull.ts).
|
|
48
|
+
function stripPhpOpeningTag(code) {
|
|
49
|
+
return code.replace(/^<\?php\s*/i, '');
|
|
50
|
+
}
|
|
51
|
+
// The real Code Snippets plugin has no independent "type" field: its REST API only has `scope`,
|
|
52
|
+
// and the snippet type is derived from it (see WPCode_Snippet::get_type_from_scope() upstream).
|
|
53
|
+
// Sending a `type` key (as this adapter used to) is silently ignored by that plugin.
|
|
54
|
+
const CODE_SNIPPETS_SCOPE_TO_LOCATION = {
|
|
55
|
+
admin: 'admin',
|
|
56
|
+
'admin-css': 'admin',
|
|
57
|
+
content: 'everywhere',
|
|
58
|
+
'footer-content': 'footer',
|
|
59
|
+
'front-end': 'frontend',
|
|
60
|
+
global: 'everywhere',
|
|
61
|
+
'head-content': 'header',
|
|
62
|
+
'single-use': 'once',
|
|
63
|
+
'site-css': 'frontend',
|
|
64
|
+
'site-footer-js': 'footer',
|
|
65
|
+
'site-head-js': 'header',
|
|
66
|
+
};
|
|
67
|
+
function typeFromScope(scope) {
|
|
68
|
+
if (scope.endsWith('-css'))
|
|
69
|
+
return 'css';
|
|
70
|
+
if (scope.endsWith('-js'))
|
|
71
|
+
return 'js';
|
|
72
|
+
if (scope.endsWith('content'))
|
|
73
|
+
return 'html';
|
|
74
|
+
return 'php';
|
|
75
|
+
}
|
|
76
|
+
function scopeFromTypeAndLocation(type, location) {
|
|
77
|
+
switch (type) {
|
|
78
|
+
case 'css': {
|
|
79
|
+
if (location === 'frontend')
|
|
80
|
+
return 'site-css';
|
|
81
|
+
if (location === 'admin')
|
|
82
|
+
return 'admin-css';
|
|
83
|
+
throw new Error(`Code Snippets does not support the "${location}" location for CSS snippets. Use one of: frontend, admin.`);
|
|
84
|
+
}
|
|
85
|
+
case 'html': {
|
|
86
|
+
if (location === 'header')
|
|
87
|
+
return 'head-content';
|
|
88
|
+
if (location === 'footer')
|
|
89
|
+
return 'footer-content';
|
|
90
|
+
if (location === 'everywhere')
|
|
91
|
+
return 'content';
|
|
92
|
+
throw new Error(`Code Snippets does not support the "${location}" location for HTML snippets. Use one of: header, footer, everywhere.`);
|
|
93
|
+
}
|
|
94
|
+
case 'js': {
|
|
95
|
+
if (location === 'header')
|
|
96
|
+
return 'site-head-js';
|
|
97
|
+
if (location === 'footer')
|
|
98
|
+
return 'site-footer-js';
|
|
99
|
+
throw new Error(`Code Snippets does not support the "${location}" location for JS snippets. Use one of: header, footer.`);
|
|
100
|
+
}
|
|
101
|
+
case 'php': {
|
|
102
|
+
if (location === 'everywhere')
|
|
103
|
+
return 'global';
|
|
104
|
+
if (location === 'frontend')
|
|
105
|
+
return 'front-end';
|
|
106
|
+
if (location === 'admin')
|
|
107
|
+
return 'admin';
|
|
108
|
+
if (location === 'once')
|
|
109
|
+
return 'single-use';
|
|
110
|
+
throw new Error(`Code Snippets does not support the "${location}" location for PHP snippets. Use one of: everywhere, frontend, admin, once.`);
|
|
111
|
+
}
|
|
112
|
+
case 'text': {
|
|
113
|
+
throw new Error('Code Snippets has no "text" snippet type. Change the sidecar "type", or push this snippet to "wpcode" instead.');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
17
117
|
class CodeSnippetsPlugin {
|
|
18
|
-
|
|
19
|
-
return
|
|
118
|
+
endpointPath() {
|
|
119
|
+
return 'code-snippets/v1/snippets';
|
|
20
120
|
}
|
|
21
121
|
fromRemote(data) {
|
|
122
|
+
const scope = String(data.scope ?? 'global');
|
|
123
|
+
const type = typeFromScope(scope);
|
|
22
124
|
return {
|
|
23
125
|
active: Boolean(data.active),
|
|
24
126
|
code: String(data.code ?? ''),
|
|
25
127
|
description: String(data.desc ?? ''),
|
|
26
128
|
id: Number(data.id),
|
|
129
|
+
insertMethod: 'auto',
|
|
130
|
+
location: CODE_SNIPPETS_SCOPE_TO_LOCATION[scope] ?? defaultLocationForType(type),
|
|
27
131
|
name: String(data.name ?? ''),
|
|
132
|
+
priority: resolvePriority(data.priority),
|
|
133
|
+
shortcodeAttributes: [],
|
|
28
134
|
tags: Array.isArray(data.tags) ? data.tags : [],
|
|
29
|
-
type
|
|
135
|
+
type,
|
|
30
136
|
};
|
|
31
137
|
}
|
|
32
|
-
toPayload(
|
|
138
|
+
toPayload({ active, code, location, name, path, priority, tags, type }) {
|
|
33
139
|
return {
|
|
34
|
-
|
|
140
|
+
active,
|
|
141
|
+
code: stripPhpOpeningTag(code),
|
|
35
142
|
desc: `Imported from ${path}`,
|
|
36
143
|
name,
|
|
37
|
-
|
|
144
|
+
priority,
|
|
145
|
+
scope: scopeFromTypeAndLocation(type, location),
|
|
146
|
+
tags,
|
|
38
147
|
};
|
|
39
148
|
}
|
|
40
149
|
}
|
|
150
|
+
// WPCode taxonomy term slugs (see wpcode_register_taxonomies() and the auto-insert location
|
|
151
|
+
// classes upstream). 'everywhere' | 'frontend_only' | 'admin_only' | 'on_demand' only apply to
|
|
152
|
+
// PHP snippets; 'site_wide_header' | 'site_wide_body' | 'site_wide_footer' apply to any type.
|
|
153
|
+
const WPCODE_PHP_ONLY_LOCATIONS = {
|
|
154
|
+
admin: 'admin_only',
|
|
155
|
+
everywhere: 'everywhere',
|
|
156
|
+
frontend: 'frontend_only',
|
|
157
|
+
once: 'on_demand',
|
|
158
|
+
};
|
|
159
|
+
const WPCODE_UNIVERSAL_LOCATIONS = {
|
|
160
|
+
body: 'site_wide_body',
|
|
161
|
+
footer: 'site_wide_footer',
|
|
162
|
+
header: 'site_wide_header',
|
|
163
|
+
};
|
|
164
|
+
const WPCODE_LOCATION_TO_CANONICAL = {
|
|
165
|
+
'admin_only': 'admin',
|
|
166
|
+
everywhere: 'everywhere',
|
|
167
|
+
'frontend_only': 'frontend',
|
|
168
|
+
'on_demand': 'once',
|
|
169
|
+
'site_wide_body': 'body',
|
|
170
|
+
'site_wide_footer': 'footer',
|
|
171
|
+
'site_wide_header': 'header',
|
|
172
|
+
};
|
|
173
|
+
function wpcodeLocationTerm(type, location) {
|
|
174
|
+
const universal = WPCODE_UNIVERSAL_LOCATIONS[location];
|
|
175
|
+
if (universal)
|
|
176
|
+
return universal;
|
|
177
|
+
if (type === 'php') {
|
|
178
|
+
const phpOnly = WPCODE_PHP_ONLY_LOCATIONS[location];
|
|
179
|
+
if (phpOnly)
|
|
180
|
+
return phpOnly;
|
|
181
|
+
}
|
|
182
|
+
const allowed = type === 'php' ? 'header, body, footer, everywhere, frontend, admin, once' : 'header, body, footer';
|
|
183
|
+
throw new Error(`WPCode does not support the "${location}" location for ${type} snippets. Use one of: ${allowed}.`);
|
|
184
|
+
}
|
|
41
185
|
class WPCodePlugin {
|
|
42
|
-
|
|
43
|
-
return
|
|
186
|
+
endpointPath() {
|
|
187
|
+
return 'loopress/v1/wpcode/snippets';
|
|
44
188
|
}
|
|
45
189
|
fromRemote(data) {
|
|
190
|
+
const type = resolveType(data.type, String(data.code ?? ''));
|
|
46
191
|
return {
|
|
47
192
|
active: Boolean(data.active),
|
|
48
193
|
code: String(data.code ?? ''),
|
|
49
194
|
description: String(data.note ?? ''),
|
|
50
195
|
id: Number(data.id),
|
|
196
|
+
insertMethod: data.insert_method === 'shortcode' ? 'shortcode' : 'auto',
|
|
197
|
+
location: WPCODE_LOCATION_TO_CANONICAL[String(data.location)] ?? defaultLocationForType(type),
|
|
51
198
|
name: String(data.title ?? ''),
|
|
199
|
+
priority: resolvePriority(data.priority),
|
|
200
|
+
shortcodeAttributes: Array.isArray(data.shortcode_attributes) ? data.shortcode_attributes.map(String) : [],
|
|
52
201
|
tags: Array.isArray(data.tags) ? data.tags : [],
|
|
53
|
-
type
|
|
202
|
+
type,
|
|
54
203
|
};
|
|
55
204
|
}
|
|
56
|
-
toPayload(
|
|
205
|
+
toPayload({ active, code, insertMethod, location, name, path, priority, shortcodeAttributes, tags, type, }) {
|
|
206
|
+
const placement = insertMethod === 'shortcode'
|
|
207
|
+
? { 'shortcode_attributes': shortcodeAttributes }
|
|
208
|
+
: { location: wpcodeLocationTerm(type, location) };
|
|
57
209
|
return {
|
|
58
|
-
|
|
210
|
+
active,
|
|
211
|
+
code: stripPhpOpeningTag(code),
|
|
59
212
|
note: `Imported from ${path}`,
|
|
60
|
-
|
|
213
|
+
priority,
|
|
214
|
+
tags,
|
|
61
215
|
title: name,
|
|
62
|
-
type
|
|
216
|
+
type,
|
|
217
|
+
...placement,
|
|
218
|
+
'insert_method': insertMethod,
|
|
63
219
|
};
|
|
64
220
|
}
|
|
65
221
|
}
|