Skip to content

Commit 34c8784

Browse files
committed
Merge remote-tracking branch 'upstream/main' into feat/tiff-image-support
# Conflicts: # packages/super-editor/src/core/DocxZipper.js
2 parents 535b006 + 11335d0 commit 34c8784

473 files changed

Lines changed: 72878 additions & 3238 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci-sdk.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ jobs:
4545
- name: Generate all artifacts
4646
run: pnpm run generate:all
4747

48-
- name: Validate SDK
49-
run: node packages/sdk/scripts/sdk-validate.mjs
50-
5148
- name: Build Node SDK
5249
run: pnpm --prefix packages/sdk/langs/node run build
50+
51+
- name: Validate SDK
52+
run: node packages/sdk/scripts/sdk-validate.mjs
Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: PR Risk Label
1+
name: PR Labels
22

33
on:
44
pull_request:
@@ -85,3 +85,28 @@ jobs:
8585
labels: [LABELS[level].name],
8686
});
8787
}
88+
89+
- name: Add community label
90+
if: >-
91+
github.event.action == 'opened' &&
92+
github.event.pull_request.author_association != 'MEMBER' &&
93+
github.event.pull_request.author_association != 'OWNER'
94+
uses: actions/github-script@v7
95+
with:
96+
script: |
97+
const owner = context.repo.owner;
98+
const repo = context.repo.repo;
99+
const label = { name: 'community', color: '7057ff' };
100+
101+
try {
102+
await github.rest.issues.getLabel({ owner, repo, name: label.name });
103+
} catch {
104+
await github.rest.issues.createLabel({ owner, repo, ...label });
105+
}
106+
107+
await github.rest.issues.addLabels({
108+
owner,
109+
repo,
110+
issue_number: context.issue.number,
111+
labels: [label.name],
112+
});

.github/workflows/release-sdk.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,15 +82,15 @@ jobs:
8282
- name: Generate all artifacts
8383
run: pnpm run generate:all
8484

85-
- name: Validate SDK
86-
run: node packages/sdk/scripts/sdk-validate.mjs
87-
8885
# ---------------------------------------------------------------
8986
# Node SDK
9087
# ---------------------------------------------------------------
9188
- name: Build Node SDK
9289
run: pnpm --prefix packages/sdk/langs/node run build
9390

91+
- name: Validate SDK
92+
run: node packages/sdk/scripts/sdk-validate.mjs
93+
9494
- name: Publish Node SDK
9595
if: ${{ !inputs.dry-run }}
9696
run: npm publish --access public --tag latest

.github/workflows/risk-assess.yml

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ name: AI Risk Assessment
22

33
# Runs AFTER risk-label.yml applies the file-path label.
44
# Only triggers for critical/sensitive PRs — low-risk PRs skip AI entirely.
5+
# Fork PRs skip AI (no access to ANTHROPIC_API_KEY) — file-path label still applies.
56
#
67
# - Updates the risk label if AI disagrees with file-path classification
78
# - Logs full details to workflow output (visible in Actions tab)
@@ -45,27 +46,36 @@ jobs:
4546
env:
4647
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4748

48-
# Skip AI for low-risk PRs
49-
- name: Skip AI for low-risk
50-
if: steps.filepath.outputs.level == 'low'
51-
run: echo "Low risk — skipping AI assessment"
52-
53-
# Install Agent SDK (only for non-low PRs)
49+
# Skip AI when low-risk or API key unavailable (e.g. fork PRs)
50+
- name: Check AI eligibility
51+
id: ai
52+
run: |
53+
if [ "${{ steps.filepath.outputs.level }}" = "low" ]; then
54+
echo "skip=true" >> $GITHUB_OUTPUT
55+
echo "Skipping AI — low risk"
56+
elif [ -z "${{ secrets.ANTHROPIC_API_KEY }}" ]; then
57+
echo "skip=true" >> $GITHUB_OUTPUT
58+
echo "Skipping AI — no API key (fork PR)"
59+
else
60+
echo "skip=false" >> $GITHUB_OUTPUT
61+
fi
62+
63+
# Install Agent SDK (only when AI will run)
5464
- name: Setup Node and Agent SDK
55-
if: steps.filepath.outputs.level != 'low'
65+
if: steps.ai.outputs.skip != 'true'
5666
uses: actions/setup-node@v4
5767
with:
5868
node-version: 20
5969

6070
- name: Install Agent SDK
61-
if: steps.filepath.outputs.level != 'low'
71+
if: steps.ai.outputs.skip != 'true'
6272
run: npm install --prefix .github/scripts @anthropic-ai/claude-agent-sdk
6373
env:
6474
NODE_ENV: production
6575

6676
# Layer 2+3: AI assessment
6777
- name: Run tiered AI assessment
68-
if: steps.filepath.outputs.level != 'low'
78+
if: steps.ai.outputs.skip != 'true'
6979
id: assess
7080
run: node .github/scripts/risk-assess.mjs ${{ env.PR_NUMBER }}
7181
env:
@@ -77,7 +87,7 @@ jobs:
7787

7888
# Update risk label if AI disagrees with file-path classification
7989
- name: Update risk label from AI
80-
if: steps.filepath.outputs.level != 'low'
90+
if: steps.ai.outputs.skip != 'true'
8191
uses: actions/github-script@v7
8292
with:
8393
script: |

.github/workflows/update-contributors.yml

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,10 @@ jobs:
3333
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
3434
PR_NUMBER="${{ inputs.pr_number }}"
3535
AUTHOR=$(gh api "repos/${{ github.repository }}/pulls/$PR_NUMBER" --jq '.user.login')
36-
ASSOCIATION=$(gh api "repos/${{ github.repository }}/pulls/$PR_NUMBER" --jq '.author_association')
3736
else
3837
AUTHOR="${{ github.event.pull_request.user.login }}"
39-
ASSOCIATION="${{ github.event.pull_request.author_association }}"
4038
fi
4139
echo "author=$AUTHOR" >> "$GITHUB_OUTPUT"
42-
echo "association=$ASSOCIATION" >> "$GITHUB_OUTPUT"
4340
4441
- name: Check if author is a bot
4542
id: check-bot
@@ -54,10 +51,10 @@ jobs:
5451
if: steps.check-bot.outputs.skip == 'false'
5552
id: check-excluded
5653
env:
54+
GH_TOKEN: ${{ steps.generate_token.outputs.token }}
5755
EXCLUDED_CONTRIBUTORS: ${{ vars.EXCLUDED_CONTRIBUTORS }}
5856
run: |
5957
AUTHOR="${{ steps.resolve.outputs.author }}"
60-
ASSOCIATION="${{ steps.resolve.outputs.association }}"
6158
6259
# Check if author is in the exclusion list (comma-separated GitHub variable)
6360
if [[ -n "$EXCLUDED_CONTRIBUTORS" ]] && echo ",$EXCLUDED_CONTRIBUTORS," | grep -qi ",$AUTHOR,"; then
@@ -66,15 +63,15 @@ jobs:
6663
exit 0
6764
fi
6865
69-
# Check if author is a repo member/collaborator via PR author_association
70-
# MEMBER = org member, OWNER = repo/org owner, COLLABORATOR = direct collaborator
71-
if [[ "$ASSOCIATION" == "MEMBER" || "$ASSOCIATION" == "OWNER" || "$ASSOCIATION" == "COLLABORATOR" ]]; then
72-
echo "$AUTHOR is a $ASSOCIATION (skipping)"
66+
# Check if author has write access to the repo (more reliable than author_association)
67+
PERMISSION=$(gh api "repos/${{ github.repository }}/collaborators/$AUTHOR/permission" --jq '.permission' 2>/dev/null || echo "none")
68+
if [[ "$PERMISSION" == "admin" || "$PERMISSION" == "maintain" || "$PERMISSION" == "write" ]]; then
69+
echo "$AUTHOR has $PERMISSION access (skipping)"
7370
echo "skip=true" >> "$GITHUB_OUTPUT"
7471
exit 0
7572
fi
7673
77-
echo "$AUTHOR is a $ASSOCIATION (not excluded)"
74+
echo "$AUTHOR has $PERMISSION access (not excluded)"
7875
echo "skip=false" >> "$GITHUB_OUTPUT"
7976
8077
- name: Checkout

apps/cli/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
},
3838
"devDependencies": {
3939
"@superdoc/document-api": "workspace:*",
40+
"@superdoc/pm-adapter": "workspace:*",
4041
"@superdoc/super-editor": "workspace:*",
4142
"@types/bun": "catalog:",
4243
"@types/node": "catalog:",

apps/cli/scripts/export-sdk-contract.ts

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { resolve, dirname } from 'node:path';
1616
import { createHash } from 'node:crypto';
1717
import { tmpdir } from 'node:os';
1818

19-
import { COMMAND_CATALOG } from '@superdoc/document-api';
19+
import { COMMAND_CATALOG, INLINE_PROPERTY_REGISTRY } from '@superdoc/document-api';
2020

2121
import { CLI_OPERATION_METADATA } from '../src/cli/operation-params';
2222
import {
@@ -60,12 +60,35 @@ const INTENT_NAMES = {
6060
'doc.delete': 'delete_content',
6161
'doc.blocks.delete': 'delete_block',
6262
'doc.format.apply': 'format_apply',
63-
'doc.format.fontSize': 'format_font_size',
64-
'doc.format.fontFamily': 'format_font_family',
65-
'doc.format.color': 'format_color',
63+
...Object.fromEntries(
64+
INLINE_PROPERTY_REGISTRY.map((entry) => [
65+
`doc.format.${entry.key}`,
66+
`format_${entry.key.replace(/[A-Z]/g, (char) => `_${char.toLowerCase()}`)}`,
67+
]),
68+
),
6669
'doc.format.align': 'format_align',
70+
'doc.styles.apply': 'styles_apply',
6771
'doc.create.paragraph': 'create_paragraph',
6872
'doc.create.heading': 'create_heading',
73+
'doc.create.sectionBreak': 'create_section_break',
74+
'doc.sections.list': 'list_sections',
75+
'doc.sections.get': 'get_section',
76+
'doc.sections.setBreakType': 'set_section_break_type',
77+
'doc.sections.setPageMargins': 'set_section_page_margins',
78+
'doc.sections.setHeaderFooterMargins': 'set_section_header_footer_margins',
79+
'doc.sections.setPageSetup': 'set_section_page_setup',
80+
'doc.sections.setColumns': 'set_section_columns',
81+
'doc.sections.setLineNumbering': 'set_section_line_numbering',
82+
'doc.sections.setPageNumbering': 'set_section_page_numbering',
83+
'doc.sections.setTitlePage': 'set_section_title_page',
84+
'doc.sections.setOddEvenHeadersFooters': 'set_section_odd_even_headers_footers',
85+
'doc.sections.setVerticalAlign': 'set_section_vertical_align',
86+
'doc.sections.setSectionDirection': 'set_section_direction',
87+
'doc.sections.setHeaderFooterRef': 'set_section_header_footer_reference',
88+
'doc.sections.clearHeaderFooterRef': 'clear_section_header_footer_reference',
89+
'doc.sections.setLinkToPrevious': 'set_section_link_to_previous',
90+
'doc.sections.setPageBorders': 'set_section_page_borders',
91+
'doc.sections.clearPageBorders': 'clear_section_page_borders',
6992
'doc.lists.list': 'list_lists',
7093
'doc.lists.get': 'get_list',
7194
'doc.lists.insert': 'insert_list',
@@ -85,6 +108,46 @@ const INTENT_NAMES = {
85108
'doc.query.match': 'query_match',
86109
'doc.mutations.preview': 'preview_mutations',
87110
'doc.mutations.apply': 'apply_mutations',
111+
'doc.create.table': 'create_table',
112+
'doc.tables.convertFromText': 'convert_text_to_table',
113+
'doc.tables.delete': 'delete_table',
114+
'doc.tables.clearContents': 'clear_table_contents',
115+
'doc.tables.move': 'move_table',
116+
'doc.tables.split': 'split_table',
117+
'doc.tables.convertToText': 'convert_table_to_text',
118+
'doc.tables.setLayout': 'set_table_layout',
119+
'doc.tables.insertRow': 'insert_table_row',
120+
'doc.tables.deleteRow': 'delete_table_row',
121+
'doc.tables.setRowHeight': 'set_table_row_height',
122+
'doc.tables.distributeRows': 'distribute_table_rows',
123+
'doc.tables.setRowOptions': 'set_table_row_options',
124+
'doc.tables.insertColumn': 'insert_table_column',
125+
'doc.tables.deleteColumn': 'delete_table_column',
126+
'doc.tables.setColumnWidth': 'set_table_column_width',
127+
'doc.tables.distributeColumns': 'distribute_table_columns',
128+
'doc.tables.insertCell': 'insert_table_cell',
129+
'doc.tables.deleteCell': 'delete_table_cell',
130+
'doc.tables.mergeCells': 'merge_table_cells',
131+
'doc.tables.unmergeCells': 'unmerge_table_cells',
132+
'doc.tables.splitCell': 'split_table_cell',
133+
'doc.tables.setCellProperties': 'set_table_cell_properties',
134+
'doc.tables.sort': 'sort_table',
135+
'doc.tables.setAltText': 'set_table_alt_text',
136+
'doc.tables.setStyle': 'set_table_style',
137+
'doc.tables.clearStyle': 'clear_table_style',
138+
'doc.tables.setStyleOption': 'set_table_style_option',
139+
'doc.tables.setBorder': 'set_table_border',
140+
'doc.tables.clearBorder': 'clear_table_border',
141+
'doc.tables.applyBorderPreset': 'apply_table_border_preset',
142+
'doc.tables.setShading': 'set_table_shading',
143+
'doc.tables.clearShading': 'clear_table_shading',
144+
'doc.tables.setTablePadding': 'set_table_padding',
145+
'doc.tables.setCellPadding': 'set_table_cell_padding',
146+
'doc.tables.setCellSpacing': 'set_table_cell_spacing',
147+
'doc.tables.clearCellSpacing': 'clear_table_cell_spacing',
148+
'doc.tables.get': 'get_table',
149+
'doc.tables.getCells': 'get_table_cells',
150+
'doc.tables.getProperties': 'get_table_properties',
88151
} as const satisfies Record<DocBackedCliOpId, string>;
89152

90153
// ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)