@loopress/cli 0.28.0 → 0.30.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 +1460 -337
- package/bin/dev.js +0 -0
- package/dist/commands/acf/pull.d.ts +9 -1
- package/dist/commands/acf/pull.js +2 -0
- package/dist/commands/acf/push.d.ts +9 -1
- package/dist/commands/acf/push.js +3 -1
- package/dist/commands/api/publish.js +1 -1
- package/dist/commands/app/push.js +1 -1
- package/dist/commands/composer/push.js +3 -3
- package/dist/commands/cpt/diff.js +5 -0
- package/dist/commands/cpt/list.d.ts +2 -0
- package/dist/commands/cpt/list.js +4 -0
- package/dist/commands/cpt/pull.d.ts +2 -0
- package/dist/commands/cpt/pull.js +4 -0
- package/dist/commands/cpt/push.d.ts +2 -0
- package/dist/commands/cpt/push.js +4 -0
- package/dist/commands/cpt/rm.d.ts +2 -0
- package/dist/commands/cpt/rm.js +3 -0
- package/dist/commands/cpt/rollback.js +5 -0
- package/dist/commands/dev.js +14 -4
- package/dist/commands/diff.js +1 -1
- package/dist/commands/doctor.d.ts +1 -0
- package/dist/commands/doctor.js +30 -2
- package/dist/commands/form/pull.d.ts +9 -1
- package/dist/commands/form/pull.js +3 -1
- package/dist/commands/form/push.d.ts +7 -1
- package/dist/commands/form/push.js +3 -1
- package/dist/commands/init.js +6 -38
- package/dist/commands/menu/pull.d.ts +7 -1
- package/dist/commands/menu/pull.js +2 -0
- package/dist/commands/menu/push.d.ts +7 -1
- package/dist/commands/menu/push.js +3 -1
- package/dist/commands/meta/diff.d.ts +2 -0
- package/dist/commands/meta/diff.js +5 -0
- package/dist/commands/meta/list.d.ts +19 -0
- package/dist/commands/meta/list.js +21 -0
- package/dist/commands/meta/pull.d.ts +2 -0
- package/dist/commands/meta/pull.js +4 -0
- package/dist/commands/meta/push.d.ts +2 -0
- package/dist/commands/meta/push.js +4 -0
- package/dist/commands/meta/rm.d.ts +2 -0
- package/dist/commands/meta/rm.js +3 -0
- package/dist/commands/meta/rollback.d.ts +2 -0
- package/dist/commands/meta/rollback.js +5 -0
- package/dist/commands/option/list.js +2 -8
- package/dist/commands/option/pull.js +4 -4
- package/dist/commands/option/push.js +2 -0
- package/dist/commands/page/push.js +3 -0
- package/dist/commands/pattern/diff.d.ts +2 -0
- package/dist/commands/pattern/diff.js +5 -0
- package/dist/commands/pattern/list.d.ts +2 -0
- package/dist/commands/pattern/list.js +3 -0
- package/dist/commands/pattern/pull.d.ts +2 -0
- package/dist/commands/pattern/pull.js +4 -0
- package/dist/commands/pattern/push.d.ts +2 -0
- package/dist/commands/pattern/push.js +4 -0
- package/dist/commands/pattern/rm.d.ts +2 -0
- package/dist/commands/pattern/rm.js +3 -0
- package/dist/commands/pattern/rollback.d.ts +2 -0
- package/dist/commands/pattern/rollback.js +5 -0
- package/dist/commands/plugin/audit.js +2 -1
- package/dist/commands/plugin/pull.d.ts +4 -0
- package/dist/commands/plugin/pull.js +56 -10
- package/dist/commands/plugin/push.js +5 -4
- package/dist/commands/project/config.d.ts +1 -0
- package/dist/commands/project/config.js +20 -1
- package/dist/commands/project/list.d.ts +1 -1
- package/dist/commands/project/list.js +6 -6
- package/dist/commands/project/pull.js +11 -8
- package/dist/commands/project/push.js +23 -18
- package/dist/commands/project/remove.js +1 -1
- package/dist/commands/project/switch.d.ts +0 -1
- package/dist/commands/project/switch.js +16 -36
- package/dist/commands/pull.js +7 -2
- package/dist/commands/push.js +14 -6
- package/dist/commands/role/diff.d.ts +2 -0
- package/dist/commands/role/diff.js +5 -0
- package/dist/commands/role/list.d.ts +2 -0
- package/dist/commands/role/list.js +4 -0
- package/dist/commands/role/pull.d.ts +2 -0
- package/dist/commands/role/pull.js +4 -0
- package/dist/commands/role/push.d.ts +2 -0
- package/dist/commands/role/push.js +4 -0
- package/dist/commands/role/rm.d.ts +2 -0
- package/dist/commands/role/rm.js +3 -0
- package/dist/commands/role/rollback.d.ts +2 -0
- package/dist/commands/role/rollback.js +5 -0
- package/dist/commands/snippet/publish.js +1 -1
- package/dist/commands/snippet/pull.js +1 -1
- package/dist/commands/snippet/push.js +1 -1
- package/dist/commands/status.d.ts +3 -3
- package/dist/commands/status.js +21 -53
- package/dist/commands/taxonomy/diff.d.ts +2 -0
- package/dist/commands/taxonomy/diff.js +5 -0
- package/dist/commands/taxonomy/list.d.ts +2 -0
- package/dist/commands/taxonomy/list.js +5 -0
- package/dist/commands/taxonomy/pull.d.ts +2 -0
- package/dist/commands/taxonomy/pull.js +4 -0
- package/dist/commands/taxonomy/push.d.ts +2 -0
- package/dist/commands/taxonomy/push.js +4 -0
- package/dist/commands/taxonomy/rm.d.ts +2 -0
- package/dist/commands/taxonomy/rm.js +3 -0
- package/dist/commands/taxonomy/rollback.d.ts +2 -0
- package/dist/commands/taxonomy/rollback.js +5 -0
- package/dist/commands/theme/pull.d.ts +6 -10
- package/dist/commands/theme/pull.js +30 -32
- package/dist/commands/theme/push.d.ts +8 -9
- package/dist/commands/theme/push.js +54 -111
- package/dist/commands/theme/style/pull.d.ts +7 -1
- package/dist/commands/theme/style/pull.js +3 -1
- package/dist/commands/theme/style/push.d.ts +8 -1
- package/dist/commands/theme/style/push.js +4 -1
- package/dist/commands/{template → theme/template}/diff.d.ts +1 -1
- package/dist/commands/{template → theme/template}/diff.js +3 -3
- package/dist/commands/{template → theme/template}/list.d.ts +2 -2
- package/dist/commands/{template → theme/template}/list.js +5 -5
- package/dist/commands/{template → theme/template}/push.d.ts +3 -1
- package/dist/commands/theme/template/push.js +65 -0
- package/dist/commands/theme/version/pull.d.ts +23 -0
- package/dist/commands/theme/version/pull.js +43 -0
- package/dist/commands/theme/version/push.d.ts +22 -0
- package/dist/commands/theme/version/push.js +123 -0
- package/dist/config/project-config.manager.d.ts +3 -3
- package/dist/config/project-config.manager.js +22 -31
- package/dist/hooks/finally.d.ts +2 -1
- package/dist/hooks/finally.js +38 -7
- package/dist/lib/api-client.js +2 -1
- package/dist/lib/app-build.js +3 -1
- package/dist/lib/app-manifest.js +2 -2
- package/dist/lib/base.d.ts +2 -2
- package/dist/lib/base.js +33 -38
- package/dist/lib/declared-type-command.d.ts +35 -0
- package/dist/lib/declared-type-command.js +192 -0
- package/dist/lib/dev-watch.d.ts +1 -1
- package/dist/lib/dev-watch.js +7 -3
- package/dist/lib/diff-state.js +1 -0
- package/dist/lib/github-release.js +4 -1
- package/dist/lib/local-callback-server.d.ts +12 -6
- package/dist/lib/local-callback-server.js +24 -23
- package/dist/lib/php-files-command.js +3 -1
- package/dist/lib/push-command.d.ts +6 -0
- package/dist/lib/push-command.js +61 -18
- package/dist/lib/put-or-create.js +3 -4
- package/dist/lib/resource-state.js +40 -86
- package/dist/lib/rollback-materialize.js +13 -24
- package/dist/lib/snapshot-store.js +2 -2
- package/dist/lib/spinner.d.ts +2 -0
- package/dist/lib/spinner.js +72 -0
- package/dist/lib/temp-admin.d.ts +10 -1
- package/dist/lib/temp-admin.js +27 -2
- package/dist/lib/validate-local.js +31 -9
- package/dist/lib/wp-authorize-flow.d.ts +10 -17
- package/dist/lib/wp-authorize-flow.js +24 -28
- package/dist/lib/wp-client.d.ts +1 -0
- package/dist/lib/wp-client.js +7 -1
- package/dist/lib/wp-site-diagnostic.js +39 -1
- package/dist/types/global-config.generated.d.ts +1 -5
- package/dist/types/project-config.generated.d.ts +28 -4
- package/dist/utils/composer.d.ts +3 -1
- package/dist/utils/composer.js +16 -7
- package/dist/utils/declared-type-format.d.ts +52 -0
- package/dist/utils/declared-type-format.js +233 -0
- package/dist/utils/option-format.d.ts +3 -1
- package/dist/utils/option-format.js +14 -3
- package/dist/utils/page-format.d.ts +5 -1
- package/dist/utils/page-format.js +7 -3
- package/dist/utils/plugin-sync.js +1 -1
- package/dist/utils/resource-dirs.d.ts +9 -3
- package/dist/utils/resource-dirs.js +18 -6
- package/dist/utils/template-format.d.ts +3 -1
- package/dist/utils/template-format.js +10 -3
- package/dist/utils/theme-css.d.ts +19 -0
- package/dist/utils/theme-css.js +100 -0
- package/oclif.manifest.json +3542 -1087
- package/package.json +40 -21
- package/schemas/global-config.schema.json +2 -6
- package/schemas/project-config.schema.json +37 -7
- package/dist/commands/seo/diff.js +0 -5
- package/dist/commands/seo/list.d.ts +0 -18
- package/dist/commands/seo/list.js +0 -58
- package/dist/commands/seo/pull.d.ts +0 -17
- package/dist/commands/seo/pull.js +0 -87
- package/dist/commands/seo/push.d.ts +0 -23
- package/dist/commands/seo/push.js +0 -176
- package/dist/commands/seo/rollback.js +0 -5
- package/dist/commands/template/push.js +0 -42
- package/dist/utils/seo-format.d.ts +0 -29
- package/dist/utils/seo-format.js +0 -18
- /package/dist/commands/{seo → cpt}/diff.d.ts +0 -0
- /package/dist/commands/{seo → cpt}/rollback.d.ts +0 -0
|
@@ -1,33 +1,45 @@
|
|
|
1
1
|
import { join } from 'node:path';
|
|
2
|
-
// The default subdirectory for each file-backed resource, relative to rootDir.
|
|
3
|
-
//
|
|
2
|
+
// The default subdirectory for each file-backed resource, relative to rootDir. Used whenever
|
|
3
|
+
// loopress.json has no `<kind>Dir` key, which is the case for a fresh `lps init`.
|
|
4
4
|
export const RESOURCE_DIR_DEFAULTS = {
|
|
5
5
|
acf: 'acf',
|
|
6
6
|
api: 'api',
|
|
7
7
|
apps: 'apps',
|
|
8
|
+
blockCss: 'theme/blocks',
|
|
9
|
+
cpt: 'cpt',
|
|
10
|
+
css: 'theme/css',
|
|
8
11
|
form: 'forms',
|
|
9
12
|
hooks: 'hooks',
|
|
10
13
|
menu: 'menus',
|
|
14
|
+
meta: 'meta',
|
|
11
15
|
options: 'options',
|
|
12
16
|
page: 'pages',
|
|
13
|
-
part: 'parts',
|
|
14
|
-
|
|
17
|
+
part: 'theme/parts',
|
|
18
|
+
pattern: 'patterns',
|
|
19
|
+
role: 'roles',
|
|
15
20
|
snippets: 'snippets',
|
|
16
|
-
|
|
21
|
+
taxonomy: 'taxonomies',
|
|
22
|
+
template: 'theme/templates',
|
|
17
23
|
themeStyles: 'theme',
|
|
18
24
|
};
|
|
19
25
|
const CONFIG_KEY = {
|
|
20
26
|
acf: 'acfDir',
|
|
21
27
|
api: 'apiDir',
|
|
22
28
|
apps: 'appsDir',
|
|
29
|
+
blockCss: 'blockCssDir',
|
|
30
|
+
cpt: 'cptDir',
|
|
31
|
+
css: 'cssDir',
|
|
23
32
|
form: 'formDir',
|
|
24
33
|
hooks: 'hooksDir',
|
|
25
34
|
menu: 'menuDir',
|
|
35
|
+
meta: 'metaDir',
|
|
26
36
|
options: 'optionsDir',
|
|
27
37
|
page: 'pageDir',
|
|
28
38
|
part: 'partDir',
|
|
29
|
-
|
|
39
|
+
pattern: 'patternDir',
|
|
40
|
+
role: 'roleDir',
|
|
30
41
|
snippets: 'snippetsDir',
|
|
42
|
+
taxonomy: 'taxonomyDir',
|
|
31
43
|
template: 'templateDir',
|
|
32
44
|
themeStyles: 'themeStylesDir',
|
|
33
45
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { type PageProblem } from './page-format.js';
|
|
1
|
+
import { type PageProblem, type SlugRule } from './page-format.js';
|
|
2
2
|
export declare const CHILD_THEME_ENDPOINT = "loopress/v1/child-theme";
|
|
3
|
+
export declare const TEMPLATE_SLUG_RULE: SlugRule;
|
|
3
4
|
export type Template = {
|
|
4
5
|
html: string;
|
|
5
6
|
postTypes?: string[];
|
|
@@ -20,6 +21,7 @@ export type ChildTheme = {
|
|
|
20
21
|
parts: Part[];
|
|
21
22
|
stylesheet: string;
|
|
22
23
|
templates: Template[];
|
|
24
|
+
unknownBlocks?: string[];
|
|
23
25
|
};
|
|
24
26
|
export declare function parseTemplateFile(slug: string, raw: string): Template;
|
|
25
27
|
export declare function parsePartFile(slug: string, raw: string): Part;
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { parseHtmlHeader, readLocalHtmlFiles, titleFromSlug } from './page-format.js';
|
|
2
2
|
export const CHILD_THEME_ENDPOINT = 'loopress/v1/child-theme';
|
|
3
|
+
// Mirrored server-side in ChildThemeController. Looser than a page slug: the template hierarchy
|
|
4
|
+
// embeds post type and taxonomy slugs as is (`taxonomy-download_tag`, `single-my_type`), and those
|
|
5
|
+
// follow sanitize_key(), so lowercase letters, digits, `_` and `-`.
|
|
6
|
+
export const TEMPLATE_SLUG_RULE = {
|
|
7
|
+
message: 'the file name must be lowercase letters, digits, "_" and "-" (e.g. "taxonomy-download_tag.html")',
|
|
8
|
+
pattern: /^[a-z0-9_-]+$/,
|
|
9
|
+
};
|
|
3
10
|
// A block delimiter as the first line (`<!-- wp:template-part ... /-->`, the usual one) is markup,
|
|
4
11
|
// not a header.
|
|
5
12
|
const BLOCK_START = /^\s*<!--\s*\/?wp:/;
|
|
@@ -28,9 +35,9 @@ export function parsePartFile(slug, raw) {
|
|
|
28
35
|
const nameArea = /^(header|footer)(-|$)/.exec(slug)?.[1] ?? 'uncategorized';
|
|
29
36
|
return { area: meta.area || nameArea, html: body, slug, title: meta.title || titleFromSlug(slug) };
|
|
30
37
|
}
|
|
31
|
-
// Same directory rules as pages/ (flat, `.html` only,
|
|
38
|
+
// Same directory rules as pages/ (flat, `.html` only), with template slugs, every problem at once.
|
|
32
39
|
export async function readLocalTemplates(templatesDir, partsDir) {
|
|
33
|
-
const templates = await readLocalHtmlFiles(templatesDir, parseTemplateFile);
|
|
34
|
-
const parts = await readLocalHtmlFiles(partsDir, parsePartFile);
|
|
40
|
+
const templates = await readLocalHtmlFiles(templatesDir, parseTemplateFile, TEMPLATE_SLUG_RULE);
|
|
41
|
+
const parts = await readLocalHtmlFiles(partsDir, parsePartFile, TEMPLATE_SLUG_RULE);
|
|
35
42
|
return { parts: parts.files, problems: [...templates.problems, ...parts.problems], templates: templates.files };
|
|
36
43
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type PageProblem } from './page-format.js';
|
|
2
|
+
export type BlockStyle = {
|
|
3
|
+
css: string;
|
|
4
|
+
name: string;
|
|
5
|
+
};
|
|
6
|
+
export type ThemeAsset = {
|
|
7
|
+
content: string;
|
|
8
|
+
path: string;
|
|
9
|
+
};
|
|
10
|
+
export type ThemeCss = {
|
|
11
|
+
assets: ThemeAsset[];
|
|
12
|
+
blocks: BlockStyle[];
|
|
13
|
+
style: string;
|
|
14
|
+
};
|
|
15
|
+
export declare const STYLE_ENTRY = "style.css";
|
|
16
|
+
export declare function bundleThemeCss(cssDir: string, blocksDir: string): Promise<{
|
|
17
|
+
css: ThemeCss;
|
|
18
|
+
problems: PageProblem[];
|
|
19
|
+
}>;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { build } from 'esbuild';
|
|
2
|
+
import { Buffer } from 'node:buffer';
|
|
3
|
+
import { existsSync } from 'node:fs';
|
|
4
|
+
import { readdir } from 'node:fs/promises';
|
|
5
|
+
import { extname, join, relative, resolve, sep } from 'node:path';
|
|
6
|
+
// The global stylesheet's entry: it @imports the rest of theme/css/ in cascade order.
|
|
7
|
+
export const STYLE_ENTRY = 'style.css';
|
|
8
|
+
// WordPress's own block name rule (register_block_type): lowercase letters, digits and dashes,
|
|
9
|
+
// starting with a letter, on both sides of the slash.
|
|
10
|
+
const BLOCK_SEGMENT = /^[a-z][a-z0-9-]*$/;
|
|
11
|
+
const ASSET_EXTENSIONS = ['.avif', '.eot', '.gif', '.jpeg', '.jpg', '.otf', '.png', '.svg', '.ttf', '.webp', '.woff', '.woff2'];
|
|
12
|
+
async function listFiles(dir) {
|
|
13
|
+
try {
|
|
14
|
+
const entries = await readdir(dir, { recursive: true, withFileTypes: true });
|
|
15
|
+
return entries
|
|
16
|
+
.filter((entry) => entry.isFile() && !entry.name.startsWith('.'))
|
|
17
|
+
.map((entry) => join(entry.parentPath, entry.name))
|
|
18
|
+
.toSorted((a, b) => a.localeCompare(b));
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
if (error.code === 'ENOENT')
|
|
22
|
+
return [];
|
|
23
|
+
throw error;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async function readBlockEntries(blocksDir, problems) {
|
|
27
|
+
const entries = [];
|
|
28
|
+
for (const file of await listFiles(blocksDir)) {
|
|
29
|
+
const segments = relative(blocksDir, file).split(sep);
|
|
30
|
+
const [namespace, block] = [segments[0], segments[1]?.replace(/\.css$/, '')];
|
|
31
|
+
if (segments.length !== 2 || extname(file) !== '.css' || !BLOCK_SEGMENT.test(namespace) || !BLOCK_SEGMENT.test(block)) {
|
|
32
|
+
problems.push({ file, message: `must be <namespace>/<block>.css, named after a block (e.g. ${join(blocksDir, 'core', 'button.css')})` });
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
entries.push({ file, name: `${namespace}/${block}` });
|
|
36
|
+
}
|
|
37
|
+
return entries;
|
|
38
|
+
}
|
|
39
|
+
function buildProblems(error) {
|
|
40
|
+
const { errors } = error;
|
|
41
|
+
if (!Array.isArray(errors))
|
|
42
|
+
throw error;
|
|
43
|
+
return errors.map((message) => ({
|
|
44
|
+
file: message.location ? `${message.location.file}:${message.location.line}` : 'esbuild',
|
|
45
|
+
message: message.text,
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
// Bundles theme/css/style.css and every theme/blocks/<namespace>/<block>.css with esbuild:
|
|
49
|
+
// @import resolved, relative url() copied to assets/ and rewritten, minified. Paths in the result
|
|
50
|
+
// are the child theme's: style.css, blocks/core/button.css, assets/inter-HASH.woff2.
|
|
51
|
+
export async function bundleThemeCss(cssDir, blocksDir) {
|
|
52
|
+
const problems = [];
|
|
53
|
+
const empty = { assets: [], blocks: [], style: '' };
|
|
54
|
+
const styleEntry = join(cssDir, STYLE_ENTRY);
|
|
55
|
+
const hasStyle = existsSync(styleEntry);
|
|
56
|
+
if (!hasStyle && (await listFiles(cssDir)).some((file) => extname(file) === '.css')) {
|
|
57
|
+
problems.push({ file: cssDir, message: `has CSS files but no ${STYLE_ENTRY}, the entry that @imports them: nothing in it would be loaded` });
|
|
58
|
+
}
|
|
59
|
+
const blocks = await readBlockEntries(blocksDir, problems);
|
|
60
|
+
if (problems.length > 0)
|
|
61
|
+
return { css: empty, problems };
|
|
62
|
+
const entryPoints = [
|
|
63
|
+
...(hasStyle ? [{ in: resolve(styleEntry), out: 'style' }] : []),
|
|
64
|
+
...blocks.map((block) => ({ in: resolve(block.file), out: `blocks/${block.name}` })),
|
|
65
|
+
];
|
|
66
|
+
if (entryPoints.length === 0)
|
|
67
|
+
return { css: empty, problems };
|
|
68
|
+
// Never written: outdir only anchors the output paths and the relative url() rewrites.
|
|
69
|
+
const outdir = resolve('/loopress-child');
|
|
70
|
+
let outputFiles;
|
|
71
|
+
try {
|
|
72
|
+
;
|
|
73
|
+
({ outputFiles } = await build({
|
|
74
|
+
assetNames: 'assets/[name]-[hash]',
|
|
75
|
+
bundle: true,
|
|
76
|
+
charset: 'utf8',
|
|
77
|
+
entryPoints,
|
|
78
|
+
loader: Object.fromEntries(ASSET_EXTENSIONS.map((extension) => [extension, 'file'])),
|
|
79
|
+
logLevel: 'silent',
|
|
80
|
+
minify: true,
|
|
81
|
+
outdir,
|
|
82
|
+
write: false,
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
return { css: empty, problems: buildProblems(error) };
|
|
87
|
+
}
|
|
88
|
+
const css = { assets: [], blocks: [], style: '' };
|
|
89
|
+
for (const output of outputFiles) {
|
|
90
|
+
const path = relative(outdir, output.path).split(sep).join('/');
|
|
91
|
+
if (path === STYLE_ENTRY)
|
|
92
|
+
css.style = output.text;
|
|
93
|
+
else if (path.startsWith('blocks/') && path.endsWith('.css'))
|
|
94
|
+
css.blocks.push({ css: output.text, name: path.slice('blocks/'.length, -'.css'.length) });
|
|
95
|
+
else
|
|
96
|
+
css.assets.push({ content: Buffer.from(output.contents).toString('base64'), path });
|
|
97
|
+
}
|
|
98
|
+
css.blocks.sort((a, b) => a.name.localeCompare(b.name));
|
|
99
|
+
return { css, problems };
|
|
100
|
+
}
|