@se-studio/project-build 1.0.113 → 1.0.115
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/CHANGELOG.md +12 -0
- package/dist/management/setupColours.js +14 -13
- package/dist/management/setupColours.js.map +1 -1
- package/dist/management/shared.d.ts +9 -4
- package/dist/management/shared.d.ts.map +1 -1
- package/dist/management/shared.js +19 -22
- package/dist/management/shared.js.map +1 -1
- package/package.json +5 -5
- package/skills/contentful-cms/core/SKILL.md +84 -0
- package/skills/contentful-cms/rich-text/SKILL.md +63 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import * as fs from 'node:fs';
|
|
4
4
|
import * as path from 'node:path';
|
|
5
5
|
import dotenv from 'dotenv';
|
|
6
|
-
import {
|
|
6
|
+
import { getManagementClient, getValidValues } from './shared.js';
|
|
7
7
|
// Load environment variables from .env.local
|
|
8
8
|
dotenv.config({ path: path.join(process.cwd(), '.env.local') });
|
|
9
9
|
// Load tailwind.config.json from the current working directory
|
|
@@ -17,7 +17,7 @@ function areTheSame(a, b) {
|
|
|
17
17
|
const hasAll = b.every((value) => aSet.has(value));
|
|
18
18
|
return hasAll;
|
|
19
19
|
}
|
|
20
|
-
async function setupColors(
|
|
20
|
+
async function setupColors(client) {
|
|
21
21
|
if (!colorOpposites || !colorOptions)
|
|
22
22
|
throw new Error('Need color options and opposites');
|
|
23
23
|
const backgroundColors = Object.keys(colorOpposites).sort();
|
|
@@ -32,39 +32,40 @@ async function setupColors(environment) {
|
|
|
32
32
|
const allForegroundColors = Array.from(new Set([...foregroundOnlyColors, ...foregroundAndBackgroundColours])).sort();
|
|
33
33
|
console.log('All background colors:', allBackgroundColors);
|
|
34
34
|
console.log('All foreground colors:', allForegroundColors);
|
|
35
|
-
const components = await
|
|
35
|
+
const components = await client.contentType.getMany({ query: {} });
|
|
36
36
|
for (const component of components.items) {
|
|
37
37
|
const backgroundColourField = component.fields.find((f) => f.id === 'backgroundColour');
|
|
38
38
|
const textColourField = component.fields.find((f) => f.id === 'textColour');
|
|
39
39
|
if (!backgroundColourField && !textColourField)
|
|
40
40
|
continue;
|
|
41
|
-
let
|
|
41
|
+
let needsWrite = false;
|
|
42
42
|
if (backgroundColourField) {
|
|
43
|
-
const currentBackgroundColors = await getValidValues(
|
|
43
|
+
const currentBackgroundColors = await getValidValues(client, component.sys.id, backgroundColourField.id);
|
|
44
44
|
if (!areTheSame(allBackgroundColors, currentBackgroundColors)) {
|
|
45
45
|
console.log(`Updating background colours for ${component.name}`);
|
|
46
46
|
backgroundColourField.validations = [{ in: allBackgroundColors }];
|
|
47
|
-
|
|
47
|
+
needsWrite = true;
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
if (textColourField) {
|
|
51
|
-
const currentTextColors = await getValidValues(
|
|
51
|
+
const currentTextColors = await getValidValues(client, component.sys.id, textColourField.id);
|
|
52
52
|
if (!areTheSame(allForegroundColors, currentTextColors)) {
|
|
53
53
|
console.log(`Updating text colours for ${component.name}`);
|
|
54
54
|
textColourField.validations = [{ in: allForegroundColors }];
|
|
55
|
-
|
|
55
|
+
needsWrite = true;
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
-
if (
|
|
58
|
+
if (needsWrite) {
|
|
59
59
|
console.log('updating', component.name);
|
|
60
|
-
const
|
|
61
|
-
await
|
|
60
|
+
const contentTypeId = component.sys.id;
|
|
61
|
+
const afterUpdate = await client.contentType.update({ contentTypeId }, component);
|
|
62
|
+
await client.contentType.publish({ contentTypeId }, afterUpdate);
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
66
|
async function run() {
|
|
66
|
-
const
|
|
67
|
-
await setupColors(
|
|
67
|
+
const client = getManagementClient();
|
|
68
|
+
await setupColors(client);
|
|
68
69
|
}
|
|
69
70
|
run()
|
|
70
71
|
.then(() => console.log('done'))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setupColours.js","sourceRoot":"","sources":["../../src/management/setupColours.ts"],"names":[],"mappings":";AACA,gEAAgE;AAChE,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"setupColours.js","sourceRoot":"","sources":["../../src/management/setupColours.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { type PlainClientAPI } from 'contentful-management';
|
|
2
|
+
/**
|
|
3
|
+
* Plain CMA client scoped to `CONTENTFUL_SPACE_ID` and `CONTENTFUL_ENVIRONMENT_NAME`.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getManagementClient(): PlainClientAPI;
|
|
6
|
+
/** @deprecated Prefer {@link getManagementClient}; same plain client. */
|
|
7
|
+
export declare const getEnvironment: typeof getManagementClient;
|
|
8
|
+
export declare function getValidValues(client: PlainClientAPI, contentTypeId: string, fieldId: string): Promise<string[]>;
|
|
9
|
+
export declare function setValidValues(client: PlainClientAPI, contentTypeId: string, fieldId: string, values: string[]): Promise<void>;
|
|
5
10
|
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/management/shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/management/shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE1E;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,cAAc,CAQpD;AAED,yEAAyE;AACzE,eAAO,MAAM,cAAc,4BAAsB,CAAC;AAElD,wBAAsB,cAAc,CAClC,MAAM,EAAE,cAAc,EACtB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,qBAWhB;AAED,wBAAsB,cAAc,CAClC,MAAM,EAAE,cAAc,EACtB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EAAE,iBASjB"}
|
|
@@ -1,9 +1,19 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { createClient } from 'contentful-management';
|
|
2
|
+
/**
|
|
3
|
+
* Plain CMA client scoped to `CONTENTFUL_SPACE_ID` and `CONTENTFUL_ENVIRONMENT_NAME`.
|
|
4
|
+
*/
|
|
5
|
+
export function getManagementClient() {
|
|
6
|
+
const spaceId = process.env.CONTENTFUL_SPACE_ID;
|
|
7
|
+
const accessToken = process.env.CONTENTFUL_MANAGEMENT_TOKEN;
|
|
8
|
+
const environmentName = process.env.CONTENTFUL_ENVIRONMENT_NAME;
|
|
9
|
+
if (!spaceId || !accessToken || !environmentName)
|
|
10
|
+
throw new Error('Env not setup');
|
|
11
|
+
return createClient({ accessToken }, { defaults: { spaceId, environmentId: environmentName } });
|
|
12
|
+
}
|
|
13
|
+
/** @deprecated Prefer {@link getManagementClient}; same plain client. */
|
|
14
|
+
export const getEnvironment = getManagementClient;
|
|
15
|
+
export async function getValidValues(client, contentTypeId, fieldId) {
|
|
16
|
+
const contentType = await client.contentType.get({ contentTypeId });
|
|
7
17
|
const field = contentType.fields.find((f) => f.id === fieldId);
|
|
8
18
|
if (!field)
|
|
9
19
|
throw new Error(`Failed to find field: ${fieldId}`);
|
|
@@ -12,25 +22,12 @@ export async function getValidValues(environment, contentTypeId, fieldId) {
|
|
|
12
22
|
throw new Error(`Field did not have validations`);
|
|
13
23
|
return validValues;
|
|
14
24
|
}
|
|
15
|
-
export async function setValidValues(
|
|
16
|
-
const contentType = await
|
|
17
|
-
if (!contentType)
|
|
18
|
-
throw new Error(`Failed to find content type: ${contentTypeId}`);
|
|
25
|
+
export async function setValidValues(client, contentTypeId, fieldId, values) {
|
|
26
|
+
const contentType = await client.contentType.get({ contentTypeId });
|
|
19
27
|
const field = contentType.fields.find((f) => f.id === fieldId);
|
|
20
28
|
if (!field)
|
|
21
29
|
throw new Error(`Failed to find field: ${fieldId}`);
|
|
22
30
|
field.validations = [{ in: values }];
|
|
23
|
-
await contentType.update();
|
|
24
|
-
}
|
|
25
|
-
export async function getEnvironment() {
|
|
26
|
-
const spaceId = process.env.CONTENTFUL_SPACE_ID;
|
|
27
|
-
const accessToken = process.env.CONTENTFUL_MANAGEMENT_TOKEN;
|
|
28
|
-
const environmentName = process.env.CONTENTFUL_ENVIRONMENT_NAME;
|
|
29
|
-
if (!spaceId || !accessToken || !environmentName)
|
|
30
|
-
throw new Error('Env not setup');
|
|
31
|
-
const client = createClient({ accessToken });
|
|
32
|
-
const space = await client.getSpace(spaceId);
|
|
33
|
-
const environment = await space.getEnvironment(environmentName);
|
|
34
|
-
return environment;
|
|
31
|
+
await client.contentType.update({ contentTypeId }, contentType);
|
|
35
32
|
}
|
|
36
33
|
//# sourceMappingURL=shared.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/management/shared.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/management/shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,MAAM,uBAAuB,CAAC;AAE1E;;GAEG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;IAChD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC;IAC5D,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC;IAEhE,IAAI,CAAC,OAAO,IAAI,CAAC,WAAW,IAAI,CAAC,eAAe;QAAE,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;IAEnF,OAAO,YAAY,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,EAAE,CAAC,CAAC;AAClG,CAAC;AAED,yEAAyE;AACzE,MAAM,CAAC,MAAM,cAAc,GAAG,mBAAmB,CAAC;AAElD,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAsB,EACtB,aAAqB,EACrB,OAAe;IAEf,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC;IAEpE,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC;IAC/D,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,OAAO,EAAE,CAAC,CAAC;IAEhE,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,KAAK,CAAC,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAEpF,IAAI,CAAC,WAAW;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpE,OAAO,WAAuB,CAAC;AACjC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAsB,EACtB,aAAqB,EACrB,OAAe,EACf,MAAgB;IAEhB,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC;IAEpE,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC;IAC/D,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,OAAO,EAAE,CAAC,CAAC;IAEhE,KAAK,CAAC,WAAW,GAAG,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IACrC,MAAM,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,EAAE,WAAW,CAAC,CAAC;AAClE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@se-studio/project-build",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.115",
|
|
4
4
|
"description": "Build tools and management scripts for SE Studio projects",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -60,19 +60,19 @@
|
|
|
60
60
|
"url": "https://github.com/Something-Else-Studio/se-core-product/issues"
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"@biomejs/biome": "^2.4.
|
|
63
|
+
"@biomejs/biome": "^2.4.9",
|
|
64
64
|
"@biomejs/js-api": "^4.0.0",
|
|
65
|
-
"@biomejs/wasm-nodejs": "^2.4.
|
|
65
|
+
"@biomejs/wasm-nodejs": "^2.4.9",
|
|
66
66
|
"change-case": "^5.4.4",
|
|
67
67
|
"chroma-js": "^3.2.0",
|
|
68
|
-
"contentful-management": "^
|
|
68
|
+
"contentful-management": "^12.0.0",
|
|
69
69
|
"dotenv": "^17.3.1"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/chroma-js": "^3.1.2",
|
|
73
73
|
"@types/node": "^22.19.15",
|
|
74
74
|
"typescript": "^6.0.2",
|
|
75
|
-
"vitest": "^4.1.
|
|
75
|
+
"vitest": "^4.1.2"
|
|
76
76
|
},
|
|
77
77
|
"scripts": {
|
|
78
78
|
"build": "node scripts/merge-contentful-skills.mjs && tsc --project tsconfig.build.json",
|
|
@@ -48,6 +48,8 @@ cms-edit open 4xKj2abcDef --id
|
|
|
48
48
|
cms-edit open /
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
+
**Slug `open`:** matches **page**, **article**, **articleType**, and **tag** by `fields.slug` (in that order; first match wins). For **template** or **navigation**, use `open <id> --id` or `cms-edit nav open`.
|
|
52
|
+
|
|
51
53
|
### Step 2: Read the snapshot
|
|
52
54
|
|
|
53
55
|
```bash
|
|
@@ -510,6 +512,88 @@ cms-edit screenshot @c0 --out after.png
|
|
|
510
512
|
agent-browser diff screenshot --baseline before.png after.png
|
|
511
513
|
```
|
|
512
514
|
|
|
515
|
+
## Revert
|
|
516
|
+
|
|
517
|
+
Field-level undo — restore fields to their original values from when the session was opened.
|
|
518
|
+
|
|
519
|
+
```bash
|
|
520
|
+
cms-edit revert @c0 heading # Revert a single field to its original value
|
|
521
|
+
cms-edit revert @c0 # Revert all fields on an entry
|
|
522
|
+
cms-edit revert --all # Revert all modified entries (session stays open)
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
Note: Entries created via `add` cannot be reverted — use `remove` instead.
|
|
526
|
+
|
|
527
|
+
## Health Check
|
|
528
|
+
|
|
529
|
+
Validate config and connectivity before running a workflow.
|
|
530
|
+
|
|
531
|
+
```bash
|
|
532
|
+
cms-edit health # Check config file, space config, Contentful connectivity, agent-browser
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
## Schema Inspection
|
|
536
|
+
|
|
537
|
+
Inspect field definitions for a content type. Prefer this over `cms-edit types <ct>` when you need full field info.
|
|
538
|
+
|
|
539
|
+
```bash
|
|
540
|
+
cms-edit schema component # Show all fields, types, enum values, link targets
|
|
541
|
+
cms-edit schema component --json # Full JSON output
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
## Sitemap
|
|
545
|
+
|
|
546
|
+
Browse all pages in the space.
|
|
547
|
+
|
|
548
|
+
```bash
|
|
549
|
+
cms-edit sitemap # All pages, sorted by slug
|
|
550
|
+
cms-edit sitemap --prefix /blog # Filter by slug prefix
|
|
551
|
+
cms-edit sitemap --status draft # Draft pages only
|
|
552
|
+
cms-edit sitemap --sort updated # Most recently updated first
|
|
553
|
+
cms-edit sitemap --tree # Tree rendering
|
|
554
|
+
cms-edit sitemap --include page,article # Include articles too
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
## Peek
|
|
558
|
+
|
|
559
|
+
Inspect a page without affecting your active session.
|
|
560
|
+
|
|
561
|
+
```bash
|
|
562
|
+
cms-edit peek /pricing # Show snapshot of /pricing; your active session is unchanged
|
|
563
|
+
cms-edit peek <id> --id # Look up by entry ID
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
## Batch Operations (run)
|
|
567
|
+
|
|
568
|
+
Run a sequence of operations from a JSON file or stdin.
|
|
569
|
+
|
|
570
|
+
```bash
|
|
571
|
+
cms-edit run --file ops.json # Run batch ops from file
|
|
572
|
+
echo '[...]' | cms-edit run # Pipe from stdin
|
|
573
|
+
cms-edit run --file ops.json --dry-run # Validate without saving
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
Supported ops: `open`, `set`, `rtf`, `rtf-replace`, `save`.
|
|
577
|
+
|
|
578
|
+
Example `ops.json`:
|
|
579
|
+
```json
|
|
580
|
+
[
|
|
581
|
+
{ "cmd": "open", "args": ["/pricing"] },
|
|
582
|
+
{ "cmd": "set", "args": ["@c0", "heading", "New Heading"] },
|
|
583
|
+
{ "cmd": "rtf", "args": ["@c1", "body", "## Section\n\nContent here."] },
|
|
584
|
+
{ "cmd": "save" }
|
|
585
|
+
]
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
## Concurrent Sessions
|
|
589
|
+
|
|
590
|
+
Use `--session <name>` or `CONTENTFUL_CMS_SESSION=<name>` to isolate parallel workflows.
|
|
591
|
+
|
|
592
|
+
```bash
|
|
593
|
+
cms-edit --session agent-1 open /pricing
|
|
594
|
+
cms-edit --session agent-2 open /blog
|
|
595
|
+
```
|
|
596
|
+
|
|
513
597
|
## Related skills
|
|
514
598
|
|
|
515
599
|
For templates see the **templates** skill; for navigation see the **navigation** skill; for rich text and embeds see the **rich-text** skill; for screenshots see the **screenshots** skill.
|
|
@@ -18,6 +18,69 @@ Use **set** for scalar and link fields; use **rtf** only for rich text fields.
|
|
|
18
18
|
|
|
19
19
|
Editing or moving existing embeds is **not supported in v1**.
|
|
20
20
|
|
|
21
|
+
## rtf replace — additional flags
|
|
22
|
+
|
|
23
|
+
These flags provide finer control when using `rtf replace`:
|
|
24
|
+
|
|
25
|
+
| Flag | Description |
|
|
26
|
+
|------|-------------|
|
|
27
|
+
| `--find-plain <text>` | Alias for `--find`; treats the search string as literal text (use when the string contains `*`) |
|
|
28
|
+
| `--ignore-marks` | Match across adjacent bold/plain splits within the same block node |
|
|
29
|
+
| `--protect-pattern <regex>` | Skip matches that fall inside spans matching this regex (e.g. existing quidget tokens) |
|
|
30
|
+
| `--dry-run` | Count matches without writing any changes |
|
|
31
|
+
| `--in-table-row <n>` | Restrict matches to row N (1-indexed; row 1 = header) |
|
|
32
|
+
| `--in-row-containing <text>` | Restrict to rows where any cell contains this text |
|
|
33
|
+
| `--in-col-containing <text>` | Restrict to the column whose header cell contains this text |
|
|
34
|
+
|
|
35
|
+
Example — replace a value only in the column whose header contains "CSP":
|
|
36
|
+
```bash
|
|
37
|
+
cms-edit rtf replace @c1 body \
|
|
38
|
+
--find 'None' \
|
|
39
|
+
--replace-plain '{*credit_card_id*:*5048345*,*field*:*foreign_transaction_fee*,*api*:*cc*}' \
|
|
40
|
+
--in-col-containing 'CSP' \
|
|
41
|
+
--mode all
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## rtf patch — JSON batch find/replace
|
|
45
|
+
|
|
46
|
+
Apply multiple find/replace operations in a single call. All ops are validated before any write.
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# From file
|
|
50
|
+
cms-edit rtf patch @c0 body --file patch.json
|
|
51
|
+
|
|
52
|
+
# From stdin
|
|
53
|
+
echo '[{"find":"old","replaceWith":"new","mode":"exactlyOne"}]' | cms-edit rtf patch @c0 body
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Each op in the JSON array supports:
|
|
57
|
+
|
|
58
|
+
| Key | Required | Description |
|
|
59
|
+
|-----|----------|-------------|
|
|
60
|
+
| `find` | yes | Search string (Markdown-interpreted) |
|
|
61
|
+
| `replaceWith` | yes | Replacement string (Markdown-interpreted unless `replaceIsMarkdown: false`) |
|
|
62
|
+
| `replaceIsMarkdown` | no | Set to `false` to treat `replaceWith` as plain text (like `--replace-plain`) |
|
|
63
|
+
| `mode` | no | `"exactlyOne"` (default), `"all"`, `"first"` |
|
|
64
|
+
| `ignoreMarks` | no | Match across adjacent bold/plain splits |
|
|
65
|
+
| `inTableCol` | no | Restrict to column N (1-indexed) |
|
|
66
|
+
| `inTableRow` | no | Restrict to row N (1-indexed) |
|
|
67
|
+
| `inRowContaining` | no | Restrict to rows where any cell contains this text |
|
|
68
|
+
| `inColContaining` | no | Restrict to the column whose header cell contains this text |
|
|
69
|
+
| `section` | no | Restrict to a document section |
|
|
70
|
+
| `protectPattern` | no | Skip matches inside spans matching this regex |
|
|
71
|
+
|
|
72
|
+
Add `--dry-run` to count matches without writing.
|
|
73
|
+
|
|
74
|
+
## rtf edit — replace field via stdin
|
|
75
|
+
|
|
76
|
+
Replace an entire rich text field by piping Markdown from stdin. Avoids shell quoting issues for long content.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
echo "## New heading\n\nNew body text." | cms-edit rtf edit @c1 body
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
In human (interactive) mode, the command prints the current Markdown to stdout first, then reads the replacement from stdin.
|
|
83
|
+
|
|
21
84
|
## Related skills
|
|
22
85
|
|
|
23
86
|
See the **core** skill for workflow, refs, and all commands.
|