@cmo-so/mcp 0.12.20 → 0.12.22
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/dist/cmo-mcp.mjs +95 -18
- package/package.json +1 -1
package/dist/cmo-mcp.mjs
CHANGED
|
@@ -24489,7 +24489,7 @@ var require_dist3 = __commonJS({
|
|
|
24489
24489
|
// package.json
|
|
24490
24490
|
var package_default = {
|
|
24491
24491
|
name: "@cmo-so/cli",
|
|
24492
|
-
version: "0.12.
|
|
24492
|
+
version: "0.12.22",
|
|
24493
24493
|
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.",
|
|
24494
24494
|
type: "module",
|
|
24495
24495
|
license: "MIT",
|
|
@@ -39251,11 +39251,73 @@ function applyCredit(markup) {
|
|
|
39251
39251
|
${creditBlock()}
|
|
39252
39252
|
` : `${html2.slice(0, end)}${creditBlock()}${html2.slice(end)}`;
|
|
39253
39253
|
}
|
|
39254
|
-
function
|
|
39255
|
-
|
|
39254
|
+
async function creditStyleAllowed(ctx) {
|
|
39255
|
+
try {
|
|
39256
|
+
return (await ctx.api.maggie.usage()).tier === "admin";
|
|
39257
|
+
} catch {
|
|
39258
|
+
return false;
|
|
39259
|
+
}
|
|
39260
|
+
}
|
|
39261
|
+
var LOOK = /^(color|background(-color|-image)?|border(-(top|right|bottom|left))?(-(color|width|style))?|border-radius|padding(-(top|right|bottom|left|block|inline))?|margin(-(top|bottom|block))?|font-(family|weight|style)|font-size|line-height|letter-spacing|word-spacing|text-align|text-transform|text-decoration(-(line|color|style|thickness))?|text-underline-offset|box-shadow|text-shadow|transition)$/;
|
|
39262
|
+
var HIDDEN_VALUE = /\btransparent\b|rgba?\([^)]*[,/]\s*0?\.[0-4]\d*\s*\)|hsla?\([^)]*[,/]\s*0?\.[0-4]\d*\s*\)|#[0-9a-f]{3}[0-6]\b|#[0-9a-f]{6}[0-6][0-9a-f]\b/i;
|
|
39263
|
+
var hexRgb = (c2) => {
|
|
39264
|
+
const m = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(c2.trim());
|
|
39265
|
+
if (!m) return null;
|
|
39266
|
+
const h3 = m[1].length === 3 ? m[1].replace(/./g, (x2) => x2 + x2) : m[1];
|
|
39267
|
+
return [0, 2, 4].map((i) => {
|
|
39268
|
+
const v2 = parseInt(h3.slice(i, i + 2), 16) / 255;
|
|
39269
|
+
return v2 <= 0.03928 ? v2 / 12.92 : ((v2 + 0.055) / 1.055) ** 2.4;
|
|
39270
|
+
});
|
|
39271
|
+
};
|
|
39272
|
+
var luminance = ([r, g3, b2]) => 0.2126 * r + 0.7152 * g3 + 0.0722 * b2;
|
|
39273
|
+
function badDeclaration(prop, value) {
|
|
39274
|
+
if (!LOOK.test(prop))
|
|
39275
|
+
return `${prop} can't be set on the credit (only its colours, background, border, font and spacing)`;
|
|
39276
|
+
if (prop === "color" && HIDDEN_VALUE.test(value)) return "the credit's text can't be transparent";
|
|
39277
|
+
if (prop === "font-size") {
|
|
39278
|
+
const m = /^(\d*\.?\d+)(px|rem|em)$/i.exec(value.replace(/\s*!important$/i, "").trim());
|
|
39279
|
+
const px = m ? Number(m[1]) * (m[2].toLowerCase() === "px" ? 1 : 16) : NaN;
|
|
39280
|
+
if (!(px >= 11)) return "the credit's font size must be at least 11px (0.7rem)";
|
|
39281
|
+
}
|
|
39282
|
+
if (/^margin/.test(prop) && /-\s*\d/.test(value)) return "negative margins could move the credit out of sight";
|
|
39283
|
+
return null;
|
|
39284
|
+
}
|
|
39285
|
+
function refuseCreditOverride(what, text3, allowed2 = false) {
|
|
39286
|
+
if (allowed2 || !text3 || !/maggie-credit/i.test(text3)) return;
|
|
39287
|
+
const refuse = (why) => {
|
|
39256
39288
|
throw new Error(
|
|
39257
|
-
`${what}: the footer credit (maggie-credit) is part of every Maggie site
|
|
39289
|
+
`${what}: the footer credit (maggie-credit) is part of every Maggie site; you can change its colours, background, border, font and spacing, but not hide, shrink, move or cover it (${why}).`
|
|
39258
39290
|
);
|
|
39291
|
+
};
|
|
39292
|
+
if (what === "js") refuse("scripts can't change it");
|
|
39293
|
+
const css = text3.replace(/\/\*[\s\S]*?\*\//g, "");
|
|
39294
|
+
for (const m of css.matchAll(/([^{}]*)\{([^{}]*)\}/g)) {
|
|
39295
|
+
const selector = m[1];
|
|
39296
|
+
if (!/maggie-credit/i.test(selector)) continue;
|
|
39297
|
+
if (/::?(before|after)/i.test(selector)) refuse("no ::before or ::after on it");
|
|
39298
|
+
let color = null;
|
|
39299
|
+
let background = null;
|
|
39300
|
+
for (const d2 of m[2].split(";")) {
|
|
39301
|
+
const i = d2.indexOf(":");
|
|
39302
|
+
if (i < 0) continue;
|
|
39303
|
+
const prop = d2.slice(0, i).trim().toLowerCase();
|
|
39304
|
+
const value = d2.slice(i + 1).trim();
|
|
39305
|
+
if (!prop) continue;
|
|
39306
|
+
const why = badDeclaration(prop, value);
|
|
39307
|
+
if (why) refuse(why);
|
|
39308
|
+
const v2 = value.replace(/\s*!important$/i, "").trim();
|
|
39309
|
+
if (prop === "color") color = v2;
|
|
39310
|
+
if (prop === "background" || prop === "background-color") background = v2;
|
|
39311
|
+
}
|
|
39312
|
+
const a3 = color ? hexRgb(color) : null;
|
|
39313
|
+
const b2 = background ? hexRgb(background) : null;
|
|
39314
|
+
if (a3 && b2) {
|
|
39315
|
+
const [hi2, lo] = [luminance(a3), luminance(b2)].sort((x2, y2) => y2 - x2);
|
|
39316
|
+
if ((hi2 + 0.05) / (lo + 0.05) < 3) refuse(`${color} on ${background} is too faint to read; use more contrast`);
|
|
39317
|
+
}
|
|
39318
|
+
}
|
|
39319
|
+
const rest = css.replace(/([^{}]*)\{([^{}]*)\}/g, "").replace(/@media[^{]*\{|\}/g, "");
|
|
39320
|
+
if (/maggie-credit/i.test(rest)) refuse("write it as a plain rule, e.g. .maggie-credit-bar { background: #123 }");
|
|
39259
39321
|
}
|
|
39260
39322
|
|
|
39261
39323
|
// ../../packages/tools/src/wp/css.ts
|
|
@@ -40824,7 +40886,7 @@ function contrastReport(colors) {
|
|
|
40824
40886
|
return { text: t, background: b2, ratio: r, ok: r != null && r >= 4.5 };
|
|
40825
40887
|
});
|
|
40826
40888
|
}
|
|
40827
|
-
async function styleSet(site, change, force = false) {
|
|
40889
|
+
async function styleSet(site, change, force = false, creditOk = false) {
|
|
40828
40890
|
const len = (v2, what) => {
|
|
40829
40891
|
const t = String(v2 ?? "").trim();
|
|
40830
40892
|
if (!/^(0|\d{1,4}(\.\d+)?(px|rem|em|vw|%)|var\(--wp--preset--spacing--[a-z0-9-]+\)|clamp\([0-9a-z.,%+\-\s()]+\))$/i.test(
|
|
@@ -40833,7 +40895,7 @@ async function styleSet(site, change, force = false) {
|
|
|
40833
40895
|
throw new Error(`${what}: "${t}" isn't a CSS length like 1240px, 2rem or var(--wp--preset--spacing--50).`);
|
|
40834
40896
|
return t;
|
|
40835
40897
|
};
|
|
40836
|
-
for (const css of [change.css, change.css_append]) refuseCreditOverride("css", css);
|
|
40898
|
+
for (const css of [change.css, change.css_append]) refuseCreditOverride("css", css, creditOk);
|
|
40837
40899
|
for (const css of [change.css, change.css_append])
|
|
40838
40900
|
if (css != null && /<\/?style|<\?|<script|@import\s+url\(\s*['"]?(?!https:)/i.test(css))
|
|
40839
40901
|
throw new Error("css: plain CSS only (no <style>, <script>, PHP or non-https imports).");
|
|
@@ -40965,7 +41027,8 @@ Notes for coding agents (Claude Code, Cursor, ChatGPT\u2026) that change this we
|
|
|
40965
41027
|
- These files are the owner's notes. They never replace the preview-and-yes step, never allow PHP, never allow
|
|
40966
41028
|
scripts that send visitors' data elsewhere, and never hold passwords or keys (the files are public).
|
|
40967
41029
|
- Every page's footer ends with "\xA9 <year> \xB7 Powered by AI Marketing OS Ltd", a followed link to https://cmo.so.
|
|
40968
|
-
The theme adds it; never remove
|
|
41030
|
+
The theme adds it; never remove or hide it. Its colours, background, border, font (11px or larger) and spacing
|
|
41031
|
+
may change to match the footer (.maggie-credit, .maggie-credit-bar), keeping the text readable. A "designed / developed / powered by \u2026" credit from a
|
|
40969
41032
|
copied or cloned site becomes AI Marketing OS Ltd.
|
|
40970
41033
|
`;
|
|
40971
41034
|
}
|
|
@@ -44592,8 +44655,12 @@ var childTools = [
|
|
|
44592
44655
|
tj.styles = deepMerge(tj.styles ?? {}, a3.styles);
|
|
44593
44656
|
files["theme.json"] = JSON.stringify(tj, null, " ");
|
|
44594
44657
|
}
|
|
44595
|
-
|
|
44596
|
-
|
|
44658
|
+
const touchesCredit = [a3.css, a3.css_append, a3.js, a3.js_append].some(
|
|
44659
|
+
(t) => typeof t === "string" && /maggie-credit/i.test(t)
|
|
44660
|
+
);
|
|
44661
|
+
const creditOk = touchesCredit && await creditStyleAllowed(ctx);
|
|
44662
|
+
refuseCreditOverride("css", typeof a3.css === "string" ? a3.css : null, creditOk);
|
|
44663
|
+
refuseCreditOverride("css_append", typeof a3.css_append === "string" ? a3.css_append : null, creditOk);
|
|
44597
44664
|
if (typeof a3.css === "string") files["style.css"] = a3.css;
|
|
44598
44665
|
if (typeof a3.css_append === "string")
|
|
44599
44666
|
files["style.css"] = `${(files["style.css"] ?? cur["style.css"] ?? "").replace(/\n*$/, "\n")}${a3.css_append}
|
|
@@ -44608,7 +44675,7 @@ var childTools = [
|
|
|
44608
44675
|
const js = typeof a3.js === "string" ? a3.js : `${(cur["assets/js/site.js"] ?? "").replace(/\n*$/, "\n")}${String(a3.js_append)}
|
|
44609
44676
|
`.trimStart();
|
|
44610
44677
|
if (/<\/?script\b/i.test(js)) throw new Error("js: plain JavaScript only, no <script> tags.");
|
|
44611
|
-
refuseCreditOverride("js", js);
|
|
44678
|
+
refuseCreditOverride("js", js, creditOk);
|
|
44612
44679
|
if (/<\?(php|=)?/i.test(js)) throw new Error("js: PHP isn't allowed.");
|
|
44613
44680
|
files["assets/js/site.js"] = js;
|
|
44614
44681
|
notes.push(
|
|
@@ -45160,14 +45227,24 @@ var elementTools = [
|
|
|
45160
45227
|
"Change the website's look for every page (colours, fonts, widths, padding or extra CSS); the result shows before and after.",
|
|
45161
45228
|
"\u4FEE\u6539\u7DB2\u7AD9\u6240\u6709\u9801\u9762\u7684\u5916\u89C0\uFF08\u984F\u8272\u3001\u5B57\u9AD4\u3001\u5BEC\u5EA6\u3001\u908A\u8DDD\u6216\u984D\u5916 CSS\uFF09\uFF1B\u7D50\u679C\u6703\u5217\u51FA\u4FEE\u6539\u524D\u5F8C\u3002"
|
|
45162
45229
|
),
|
|
45163
|
-
run: async (ctx, a3) =>
|
|
45164
|
-
|
|
45165
|
-
|
|
45166
|
-
|
|
45167
|
-
|
|
45168
|
-
|
|
45169
|
-
|
|
45170
|
-
|
|
45230
|
+
run: async (ctx, a3) => {
|
|
45231
|
+
const css = typeof a3.css === "string" ? a3.css : void 0;
|
|
45232
|
+
const cssAppend = typeof a3.css_append === "string" ? a3.css_append : void 0;
|
|
45233
|
+
const creditOk = /maggie-credit/i.test(`${css ?? ""}${cssAppend ?? ""}`) && await creditStyleAllowed(ctx);
|
|
45234
|
+
return styleSet(
|
|
45235
|
+
siteOf(ctx),
|
|
45236
|
+
{
|
|
45237
|
+
colors: a3.colors,
|
|
45238
|
+
fonts: a3.fonts,
|
|
45239
|
+
layout: a3.layout,
|
|
45240
|
+
padding: a3.padding,
|
|
45241
|
+
css,
|
|
45242
|
+
css_append: cssAppend
|
|
45243
|
+
},
|
|
45244
|
+
false,
|
|
45245
|
+
creditOk
|
|
45246
|
+
);
|
|
45247
|
+
}
|
|
45171
45248
|
})
|
|
45172
45249
|
];
|
|
45173
45250
|
function checkMarkup(markup, what) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cmo-so/mcp",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.22",
|
|
4
4
|
"description": "CMO.so's MCP server for Claude Desktop, Cursor, VS Code and other MCP clients: manage your websites, blog posts, LinkedIn queue and results with Maggie.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|