@cmo-so/cli 0.12.5 → 0.12.6
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 +1 -0
- package/dist/cmo.mjs +125 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,6 +36,7 @@ cmo wp status | map [--sections] | pages [--search …] [--missing-seo] | sectio
|
|
|
36
36
|
cmo wp page <page> [--section s2] a page's sections (ids: m… bands, s… reading column, a… sidebar)
|
|
37
37
|
cmo wp page create --title … --from sections.json [--parent …] [--publish] [--menu-parent …]
|
|
38
38
|
cmo wp page update <page> title=… slug=… status=… | delete <page> [--redirect-to …] | undo <page>
|
|
39
|
+
cmo wp page publish <page> [--homepage] | cmo wp home <page> [--posts-page …] [--latest-posts]
|
|
39
40
|
cmo wp page duplicate <page> --title … --replace Fairfax=Vienna
|
|
40
41
|
cmo wp section add <page> <type> --from slots.json [--after s1] [--preview]
|
|
41
42
|
cmo wp section update <page> <section> --from change.json [--preview] (edits | slots | faq)
|
package/dist/cmo.mjs
CHANGED
|
@@ -16181,6 +16181,27 @@ async function changePage(ctx, a, fn) {
|
|
|
16181
16181
|
undo: "wp_page_undo goes back to the version before this change."
|
|
16182
16182
|
};
|
|
16183
16183
|
}
|
|
16184
|
+
var findAllBlocks = (list3) => list3.flatMap((b) => [b, ...findAllBlocks(b.inner)]);
|
|
16185
|
+
async function setHome(site, id, postsPage) {
|
|
16186
|
+
const before = await call(site, {
|
|
16187
|
+
path: "/wp/v2/settings",
|
|
16188
|
+
query: { _fields: "show_on_front,page_on_front,page_for_posts" }
|
|
16189
|
+
});
|
|
16190
|
+
const body = { show_on_front: "page", page_on_front: id };
|
|
16191
|
+
if (postsPage !== void 0) body.page_for_posts = postsPage;
|
|
16192
|
+
if (postsPage === id) throw new Error("The homepage and the posts page can't be the same page.");
|
|
16193
|
+
const after = await call(site, {
|
|
16194
|
+
method: "POST",
|
|
16195
|
+
path: "/wp/v2/settings",
|
|
16196
|
+
query: { _fields: "show_on_front,page_on_front,page_for_posts" },
|
|
16197
|
+
body
|
|
16198
|
+
});
|
|
16199
|
+
return {
|
|
16200
|
+
before,
|
|
16201
|
+
after,
|
|
16202
|
+
undo: before.show_on_front === "page" && before.page_on_front ? `wp_site_home_set page ${before.page_on_front}` : "wp_site_home_set latest_posts true"
|
|
16203
|
+
};
|
|
16204
|
+
}
|
|
16184
16205
|
function position(a) {
|
|
16185
16206
|
return {
|
|
16186
16207
|
after: a.after || void 0,
|
|
@@ -16553,6 +16574,103 @@ var pageTools = [
|
|
|
16553
16574
|
};
|
|
16554
16575
|
}
|
|
16555
16576
|
}),
|
|
16577
|
+
tool({
|
|
16578
|
+
name: "wp_page_publish",
|
|
16579
|
+
description: "Publish a page (a draft or private page) so visitors and search engines see it. Checks it first: one H1, an SEO title and description (warns when missing). homepage: true also makes it the site's homepage. Afterwards the live page is opened to confirm it works. To take it down again, wp_page_update status draft.",
|
|
16580
|
+
parameters: {
|
|
16581
|
+
type: "object",
|
|
16582
|
+
properties: {
|
|
16583
|
+
page: PAGE,
|
|
16584
|
+
homepage: bool("Also make it the site's homepage."),
|
|
16585
|
+
expect_modified: EXPECT
|
|
16586
|
+
},
|
|
16587
|
+
required: ["page"]
|
|
16588
|
+
},
|
|
16589
|
+
group: "site",
|
|
16590
|
+
need: WRITE,
|
|
16591
|
+
risk: "W3",
|
|
16592
|
+
gates: [...GATES],
|
|
16593
|
+
confirm: (a, lang) => say(
|
|
16594
|
+
lang,
|
|
16595
|
+
`Publish page ${q2(a.page, "")} on your website${a.homepage ? " and make it the homepage" : ""}.`,
|
|
16596
|
+
`\u767C\u4F48\u7DB2\u7AD9\u4E0A\u7684\u9801\u9762 ${q2(a.page, "")}${a.homepage ? "\uFF0C\u4E26\u8A2D\u70BA\u9996\u9801" : ""}\u3002`
|
|
16597
|
+
),
|
|
16598
|
+
run: async (ctx, a) => {
|
|
16599
|
+
const site = siteOf(ctx);
|
|
16600
|
+
const p = await findPage(site, a.page, true);
|
|
16601
|
+
checkFresh(p, a.expect_modified);
|
|
16602
|
+
const m = p.meta ?? {};
|
|
16603
|
+
const blocks = parse(p.content?.raw ?? "");
|
|
16604
|
+
const h1 = findAllBlocks(blocks).filter((b) => b.name === "core/heading" && Number(b.attrs.level) === 1).length;
|
|
16605
|
+
const warnings = [
|
|
16606
|
+
h1 === 1 ? "" : h1 === 0 ? "The page has no H1 in its content (a template may add one)." : `The page has ${h1} H1 headings.`,
|
|
16607
|
+
m.maggie_seo_title ? "" : "No SEO title: the page title is used.",
|
|
16608
|
+
m.maggie_seo_description ? "" : "No meta description: set one with wp_seo_set."
|
|
16609
|
+
].filter(Boolean);
|
|
16610
|
+
const wasStatus = p.status;
|
|
16611
|
+
const saved = p.status === "publish" ? p : await savePage(site, p.id, null, { status: "publish" });
|
|
16612
|
+
let home = null;
|
|
16613
|
+
if (a.homepage) home = await setHome(site, p.id);
|
|
16614
|
+
const live = await check(site, saved.link, "publish");
|
|
16615
|
+
return {
|
|
16616
|
+
published: true,
|
|
16617
|
+
id: p.id,
|
|
16618
|
+
path: path(saved.link),
|
|
16619
|
+
before: wasStatus,
|
|
16620
|
+
homepage: home,
|
|
16621
|
+
check: live,
|
|
16622
|
+
warnings
|
|
16623
|
+
};
|
|
16624
|
+
}
|
|
16625
|
+
}),
|
|
16626
|
+
tool({
|
|
16627
|
+
name: "wp_site_home_set",
|
|
16628
|
+
description: "Choose the site's homepage (a published page) and, optionally, the page that lists the blog posts. Returns the previous setting so it can be put back. latest_posts: true shows the newest posts as the homepage instead.",
|
|
16629
|
+
parameters: {
|
|
16630
|
+
type: "object",
|
|
16631
|
+
properties: {
|
|
16632
|
+
page: str2("The page to show as the homepage (path, slug or id)."),
|
|
16633
|
+
posts_page: str2('The page that lists the blog posts (optional; "" to clear).'),
|
|
16634
|
+
latest_posts: bool("Show the newest posts as the homepage instead of a page.")
|
|
16635
|
+
}
|
|
16636
|
+
},
|
|
16637
|
+
group: "site",
|
|
16638
|
+
need: WRITE,
|
|
16639
|
+
risk: "W3",
|
|
16640
|
+
gates: [...GATES],
|
|
16641
|
+
confirm: (a, lang) => a.latest_posts ? say(lang, "Show your newest posts as your website's homepage.", "\u628A\u7DB2\u7AD9\u9996\u9801\u6539\u70BA\u986F\u793A\u6700\u65B0\u6587\u7AE0\u3002") : say(
|
|
16642
|
+
lang,
|
|
16643
|
+
`Make ${q2(a.page, "that page")} your website's homepage.`,
|
|
16644
|
+
`\u628A ${q2(a.page, "\u8A72\u9801\u9762")} \u8A2D\u70BA\u7DB2\u7AD9\u9996\u9801\u3002`
|
|
16645
|
+
),
|
|
16646
|
+
run: async (ctx, a) => {
|
|
16647
|
+
const site = siteOf(ctx);
|
|
16648
|
+
if (a.latest_posts) {
|
|
16649
|
+
const before = await call(site, {
|
|
16650
|
+
path: "/wp/v2/settings",
|
|
16651
|
+
query: { _fields: "show_on_front,page_on_front,page_for_posts" }
|
|
16652
|
+
});
|
|
16653
|
+
await call(site, {
|
|
16654
|
+
method: "POST",
|
|
16655
|
+
path: "/wp/v2/settings",
|
|
16656
|
+
query: { _fields: "show_on_front" },
|
|
16657
|
+
body: { show_on_front: "posts" }
|
|
16658
|
+
});
|
|
16659
|
+
return { before, after: { show_on_front: "posts" } };
|
|
16660
|
+
}
|
|
16661
|
+
if (!a.page) throw new Error("Which page should be the homepage?");
|
|
16662
|
+
const p = await findPage(site, a.page);
|
|
16663
|
+
if (p.status !== "publish")
|
|
16664
|
+
throw new Error(
|
|
16665
|
+
`${path(p.link)} isn't published yet: publish it first (wp_page_publish homepage: true does both).`
|
|
16666
|
+
);
|
|
16667
|
+
let postsPage;
|
|
16668
|
+
if (typeof a.posts_page === "string")
|
|
16669
|
+
postsPage = a.posts_page === "" ? 0 : (await findPage(site, a.posts_page)).id;
|
|
16670
|
+
const r = await setHome(site, p.id, postsPage);
|
|
16671
|
+
return { ...r, check: await check(site, `${site.url ?? ""}/`, "publish") };
|
|
16672
|
+
}
|
|
16673
|
+
}),
|
|
16556
16674
|
tool({
|
|
16557
16675
|
name: "wp_page_delete",
|
|
16558
16676
|
description: "Move a page to the WordPress trash (restorable for 30 days) and redirect its address (301) to another page, by default its parent or the homepage.",
|
|
@@ -21088,7 +21206,7 @@ var program = new Command();
|
|
|
21088
21206
|
// package.json
|
|
21089
21207
|
var package_default = {
|
|
21090
21208
|
name: "@cmo-so/cli",
|
|
21091
|
-
version: "0.12.
|
|
21209
|
+
version: "0.12.6",
|
|
21092
21210
|
description: "CMO.so on the command line: your websites, ideas, blog posts, LinkedIn queue and results, plus a local MCP server for Claude Desktop, Cursor and other MCP clients.",
|
|
21093
21211
|
type: "module",
|
|
21094
21212
|
license: "MIT",
|
|
@@ -32059,6 +32177,9 @@ function registerWp(program3) {
|
|
|
32059
32177
|
wp.command("pages").description("find pages").option("--search <words>", "words in the title").option("--missing-seo", "only pages without their own SEO title or description").option("--template <slug>", "only this template").action(
|
|
32060
32178
|
(o, c) => run(g(c), "wp_pages_list", { search: o.search, missing_seo: !!o.missingSeo, template: o.template })
|
|
32061
32179
|
);
|
|
32180
|
+
wp.command("home [page]").description("choose the homepage (a published page), the posts page, or the latest posts").option("--posts-page <page>", 'the page that lists the blog posts ("" to clear)').option("--latest-posts", "show the newest posts as the homepage").action(
|
|
32181
|
+
(p, o, c) => run(g(c), "wp_site_home_set", { page: p, posts_page: o.postsPage, latest_posts: !!o.latestPosts })
|
|
32182
|
+
);
|
|
32062
32183
|
wp.command("sections").description("the section library and page blueprints").action(
|
|
32063
32184
|
(_o, c) => run(
|
|
32064
32185
|
g(c),
|
|
@@ -32103,6 +32224,9 @@ function registerWp(program3) {
|
|
|
32103
32224
|
replace: pairs(o.replace).map(([find2, replace2]) => ({ find: find2, replace: replace2 }))
|
|
32104
32225
|
})
|
|
32105
32226
|
);
|
|
32227
|
+
page.command("publish <page>").description("publish a page (checks it first); --homepage also makes it the homepage").option("--homepage", "make it the site's homepage").action(
|
|
32228
|
+
(p, o, c) => run(g(c), "wp_page_publish", { page: p, homepage: !!o.homepage })
|
|
32229
|
+
);
|
|
32106
32230
|
page.command("undo <page>").description("back to the version before the last change").action((p, _o, c) => run(g(c), "wp_page_undo", { page: p }));
|
|
32107
32231
|
const section = wp.command("section").description("add, change, move or remove a page's sections");
|
|
32108
32232
|
const pos = (cmd) => cmd.option("--after <section>", "after this section (id or type)").option("--before <section>", "before this section").option("--region <region>", "main, story or aside").option("--index <n>", "position in the region");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cmo-so/cli",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.6",
|
|
4
4
|
"description": "CMO.so on the command line: your websites, ideas, blog posts, LinkedIn queue and results, plus a local MCP server for Claude Desktop, Cursor and other MCP clients.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|