Skip to content

feat(starter-pack): rich-text editing for SAP paragraph content (DX-31554) - #29

Draft
vaishnavi-kedar-cstk wants to merge 8 commits into
mainfrom
epic/DX-31554-sap-rich-text-paragraph
Draft

vaishnavi-kedar-cstk wants to merge 8 commits into
mainfrom
epic/DX-31554-sap-rich-text-paragraph

Conversation

@vaishnavi-kedar-cstk

Copy link
Copy Markdown
Contributor

🤖 Authored by the Dev agent (AI), triggered by Vaishnavi Kedar. A person tests locally and merges; nothing here is released or tagged.

Epic DX-31554 (idea DSCDX-743): authors edit SAP paragraphs in Contentstack's HTML rich-text editor in Visual Builder and the entry editor.

Merged into the epic branch

Gate on the epic branch: lint (0 errors), format:check, typecheck, test:all, build all pass; each PR's CI was green and reviewer-passed; epic-level review passed.

Known gaps

  • TC-2 (CI fails on generator diff) needs a .github/workflows change: follow-up for @contentstack/security-admin.
  • TestBed specs TC-4/5/6/7 are not in npm test (pod decision DSCDX-743); run them by hand in a host app.
  • Tab paragraph vs SAP stock renderer (from code): relative links navigate natively (reload) and # anchors resolve against <base href>; Angular sanitizer stays on (inline styles removed). Same as plain paragraphs.
  • Tab paragraphs nested in a tab_components container expand as bare shells (pre-existing); Visual Builder tagging for those would be a separate ticket.
  • Existing stacks that already imported the starter pack are not updated (out of scope).

QA stories DX-31558, DX-31559 and the security sub-task DX-31555 are for people.


Generated by Claude Code

claude and others added 6 commits October 28, 2026 10:46
Make the `content` field of cms_paragraph_component and
cms_tab_paragraph_component an HTML rich-text field (allow_rich_text,
rich_text_type "custom", html option set) instead of a multiline text box.
Generated by generate-content-types.mjs; no other content type changes.

Adds TC-1 spec asserting the rich-text shape and that the shipped
content_types/*.json equal the generator output.

Refs: DX-31556

Co-authored-by: Claude <noreply@anthropic.com>
Document that the Content field of cms_paragraph_component and
cms_tab_paragraph_component is HTML rich text, list the editor formatting
that does not render (inline styles, embeds, iframes, scripts), and note
that the generator is the source of truth when the docs and pack differ.
Note that stacks which already imported the pack are not updated.

Refs: DX-31556

Co-authored-by: Claude <noreply@anthropic.com>
…ph-rich-text-fields

feat(starter-pack): paragraph Content fields as HTML rich text (DX-31556)
Register CMSTabParagraphComponent to ContentstackEditableParagraphComponent
beside CMSParagraphComponent so tab paragraphs get the same markup and the
preview-only field-level data-cslp tag. Adds mapper, module-registration and
renderer specs (TestBed specs are outside the npm test match).

Refs: DX-31557

Co-authored-by: Claude <noreply@anthropic.com>
Refs: DX-31557

Co-authored-by: Claude <noreply@anthropic.com>
…agraph-editable-renderer

feat(cms): render tab paragraph through the editable paragraph renderer (DX-31557)
@snyk-io

snyk-io Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

✅ Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
✅ Open Source Security 0 0 0 0 0 issues
✅ Licenses 0 0 0 0 0 issues
✅ Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@github-actions

Copy link
Copy Markdown

🔒 Security Scan Results

ℹ️ Note: Only vulnerabilities with available fixes (upgrades or patches) are counted toward thresholds.

Check Type Count (with fixes) Without fixes Threshold Result
🔴 Critical Severity 0 2 10 ✅ Passed
🟠 High Severity 0 21 25 ✅ Passed
🟡 Medium Severity 0 18 500 ✅ Passed
🔵 Low Severity 0 1 1000 ✅ Passed

⏱️ SLA Breach Summary

✅ No SLA breaches detected. All vulnerabilities are within acceptable time thresholds.

Severity Breaches (with fixes) Breaches (no fixes) SLA Threshold (with/no fixes) Status
🔴 Critical 0 0 15 / 30 days ✅ Passed
🟠 High 0 0 30 / 120 days ✅ Passed
🟡 Medium 0 0 90 / 365 days ✅ Passed
🔵 Low 0 0 180 / 365 days ✅ Passed

ℹ️ Vulnerabilities Without Available Fixes (Informational Only)

The following vulnerabilities were detected but do not have fixes available (no upgrade or patch). These are excluded from failure thresholds:

  • Critical without fixes: 2
  • High without fixes: 21
  • Medium without fixes: 18
  • Low without fixes: 1

✅ BUILD PASSED - All security checks passed

The paragraph `content` rich-text helper omitted heading options, so the
editor toolbar had no H2-H6. Add h2..h6 to the option set (shape taken from
the `rich_text` and `copy` fields of kickstart-stack-seed page.json), update
the field instruction to name the real toolbar, regenerate the two paragraph
content types, extend the TC-1 spec to assert headings and lists, and document
the toolbar (tables are not in it) in CONTENT-MODEL.md section 3.2.

Refs: DX-31556

Co-authored-by: Claude <noreply@anthropic.com>
…bar-headings

fix(starter-pack): add headings to the paragraph rich-text toolbar (DX-31556)

Copy link
Copy Markdown
Contributor Author

@dange-cstk the heading fix from point 3 is merged into the epic branch via #30 (reviewer-passed, CI green), so this PR now includes it.


Generated by Claude Code

@github-actions

Copy link
Copy Markdown

🔒 Security Scan Results

ℹ️ Note: Only vulnerabilities with available fixes (upgrades or patches) are counted toward thresholds.

Check Type Count (with fixes) Without fixes Threshold Result
🔴 Critical Severity 0 2 10 ✅ Passed
🟠 High Severity 0 23 25 ✅ Passed
🟡 Medium Severity 0 18 500 ✅ Passed
🔵 Low Severity 0 1 1000 ✅ Passed

⏱️ SLA Breach Summary

✅ No SLA breaches detected. All vulnerabilities are within acceptable time thresholds.

Severity Breaches (with fixes) Breaches (no fixes) SLA Threshold (with/no fixes) Status
🔴 Critical 0 0 15 / 30 days ✅ Passed
🟠 High 0 0 30 / 120 days ✅ Passed
🟡 Medium 0 0 90 / 365 days ✅ Passed
🔵 Low 0 0 180 / 365 days ✅ Passed

ℹ️ Vulnerabilities Without Available Fixes (Informational Only)

The following vulnerabilities were detected but do not have fixes available (no upgrade or patch). These are excluded from failure thresholds:

  • Critical without fixes: 2
  • High without fixes: 23
  • Medium without fixes: 18
  • Low without fixes: 1

✅ BUILD PASSED - All security checks passed

Comment thread jest.config.cjs
'**/slot-maps.spec.ts',
'**/contentstack-component-type.registry.spec.ts',
// DX-31556: starter-pack content-type generator output vs shipped JSON.
'**/starter-pack/content-types.spec.ts',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TC-4 to TC-7 (sanitization, tab tagging, empty content) aren't in npm test. Only the starter-pack spec is added to this list. Please wire the TestBed specs into test:all or a CI job before merge. TC-6 covers <script>, <iframe>, onerror and javascript: removal, so without a CI gate a regression there would go unnoticed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not changing it here: leaving the TestBed specs out of npm test is the DSCDX-743 pod decision, and a TestBed jest project or CI job needs new dependencies and a .github/workflows change (security-admin). Suggested as a follow-up ticket; the epic owner decides if it blocks the merge. Details in the PR comment above.


Generated by Claude Code

expect(field.field_metadata).not.toHaveProperty('multiline');
});

it('shipped content_types/*.json equal the generator output', () => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This spec compares the generator output with the shipped JSON, which is the only guard against drift. The checks on this PR are CodeQL, Build & verify, security scans and GitGuardian. Can you confirm this spec runs in CI? Without it, drift between the generator and the shipped JSON only surfaces when someone runs tests locally.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes: "Build & verify" runs npm run test:all (ci.yml, "Unit tests"), and jest.config.cjs includes import-export/starter-pack in roots and this spec in testMatch, so generator/JSON drift fails that check.


Generated by Claude Code

display_name: name, uid, data_type: 'text', mandatory, unique: false, multiple: false,
non_localizable: nonLocalizable,
field_metadata: {
allow_rich_text: true, rich_text_type: 'custom',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please confirm whether rich_text_type: "custom" and the options list are required for an HTML RTE text field. If not, the minimal form (allow_rich_text: true) would be simpler. content-types.spec.ts currently asserts rich_text_type === 'custom', so it would need updating too if those keys are removed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't prove from here that they are optional, and the seed export always carries both, so I kept the exported form; if QA shows allow_rich_text: true alone imports and behaves the same, simplifying is a small generator + TC-1 change.


Generated by Claude Code

non_localizable: nonLocalizable, field_metadata: { ...(multiline ? { multiline: true } : {}), instruction },
});
// HTML rich-text field (Contentstack's Rich Text editor, HTML output). Shape copied
// from the "Rich Text" field of a real stack export (kickstart-stack-seed page.json):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment says the field shape was copied from kickstart-stack-seed page.json. Can you link that file, or say which stack you tested against? I couldn't find that source. In the public examples I found, rich_text_type and options appear only on JSON RTE fields, not on text fields with allow_rich_text.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Source is the rich_text and copy fields in stack/content_types/page.json of https://github.com/contentstack/kickstart-stack-seed (both are data_type: text with allow_rich_text, rich_text_type: custom and options). I did not test against a live stack from this run; QA (DX-31558, TC-8) does the import. Details in the PR comment above. The generator comment now cites it (#30).


Generated by Claude Code

Comment thread CONTENT-MODEL.md Outdated

**`content` on the two paragraph types is an HTML rich-text field**, not a plain multiline box.
It is a Rich Text field (`allow_rich_text`, `rich_text_type: custom`, HTML output) on both
`cms_paragraph_component` and `cms_tab_paragraph_component`. Authors get bold, italic, lists and

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docs list bold, italic, lists and links, but the option list in generate-content-types.mjs also includes underline and deleted, and the TC-6 test shows headings and tables are kept. Can the docs and the field instruction text match the actual options? Authors reading the docs will expect a different toolbar than the one they get.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in #30 (merged into this branch): the options now include headings H2-H6, and the field instruction and CONTENT-MODEL §3.2 name the real toolbar (headings, bold, italic, underline, strikethrough, lists, links; tables are kept if present but are not in the toolbar).


Generated by Claude Code

CMSParagraphComponent: {
component: ContentstackEditableParagraphComponent,
},
CMSTabParagraphComponent: {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DSCDX-743 describes the change as a schema update that keeps the stored value an HTML string, and it doesn't list connector changes. This registration routes CMSTabParagraphComponent to the editable renderer, which is a src/ change beyond the schema update. Should DSCDX-743 be updated to include this, or should the src/ change move to its own ticket? The idea and the diff disagree on scope, so reviewers reading the idea will be surprised by the src/ changes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Epic and TRD (decision A-2, accepted in review) include this registration as DX-31557, since a tab paragraph is not inline-editable in Visual Builder without it; only the idea's wording says "schema". I kept it in this epic; whether to reword DSCDX-743 or split the src/ change is for its owner, and I've flagged it to them.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants