Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c94f7ca
AXON-1020: installed Atlassian editor, changed prosemirror version
BHulovatyi Sep 3, 2025
ff2a75b
AXON-1020: Removed unnecessary code and files
BHulovatyi Sep 3, 2025
13bebbe
AXON-1038: Add basic editor to codebase
om-ukr Sep 3, 2025
d5a5bd7
AXON-1020: Added button "save" and "Cancel"
BHulovatyi Sep 4, 2025
0e36e04
AXON-1020: Added ADF, json-transformer, markdown-transformer
BHulovatyi Sep 8, 2025
89d0055
AXON-1040: Move related styles to old editor component
om-ukr Sep 8, 2025
b5314a1
AXON-1036: Add feature flag to switch between old editor and new one
om-ukr Sep 9, 2025
e74c6b3
AXON-1039: Use WikiMarkupTransformer to send data
om-ukr Sep 11, 2025
65ec6ab
AXON-1103: AbstractIssueEditorPage use simple textarea
BHulovatyi Sep 11, 2025
0c3575b
AXON-1103: returned isAtlaskitEditorFFReceived
BHulovatyi Sep 12, 2025
c977ae8
AXON-1106 Update editor dependencies and exclude pdfjs-dist from report
om-ukr Sep 12, 2025
1490c7c
AXON-1126: Added Atlassian Editor to Create Issue page
BHulovatyi Sep 15, 2025
2079901
AXON-1105: Add tests
om-ukr Sep 16, 2025
8c1641b
AXON-1105: Increase AssetSize theshold
om-ukr Sep 16, 2025
0339943
AXON-1105: Update tests timeouts
om-ukr Sep 16, 2025
e42a952
AXON-1144: Added EditRenderedTextArea and JiraIssueTextAreaEditor, ad…
BHulovatyi Sep 17, 2025
a34b5cf
AXON-1144: Added this.coerceToString to JiraIssueTextAreaEditor
BHulovatyi Sep 17, 2025
1eed8aa
AXON-1144: Moved AtlaskitEditor from CreateIssuePage.tsx to AbstractI…
BHulovatyi Sep 17, 2025
105f249
AXON-1105: update failing test
om-ukr Sep 17, 2025
7dd89fe
AXON-1105: comment out failing test
om-ukr Sep 18, 2025
b001bc1
AXON-1162: Attempt to fix run extension:package
om-ukr Sep 18, 2025
a8330a5
AXON-1105: add fixes for other slow tests
om-ukr Sep 18, 2025
1441e09
AXON-1163: Fixed style in Editor
BHulovatyi Sep 18, 2025
a7474b6
AXON-1163: removed some !important, add z-index: 1 to ak-editor-main-…
BHulovatyi Sep 18, 2025
c8692bc
AXON-1163: removed z-index to dropdown-item
BHulovatyi Sep 18, 2025
628d4be
Update ff name and remove runInBand
om-ukr Sep 19, 2025
6268df8
AXON-1177: Remove JIRA RTE
om-ukr Sep 19, 2025
31b7035
Revert prosemirror deps versions
om-ukr Sep 19, 2025
27b9b4b
Fix review comments
om-ukr Sep 22, 2025
2aacd78
Second fix of review comments
om-ukr Sep 23, 2025
749b6a3
AXON-1176: Installed editor-plugin-media and added base functionality
BHulovatyi Sep 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .audit-ci.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"package-manager": "npm",
"low": true,
"allowlist": [
"pdfjs-dist"
],
"show-not-found": true
}
10 changes: 6 additions & 4 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ jobs:
- name: Install dependencies
run: |
npm ci --no-audit

- name: Run vulnerability audit
run: npm audit

# "There is no Vulnerability in Media Viewer after 48.5.4. since it was fixed by patching, but npm audit still reports it.",
# So that switched to audit-ci with allowlist
run: npx audit-ci --config=".audit-ci.json"

- name: Run linter
run: npm run lint

Expand Down Expand Up @@ -110,4 +112,4 @@ jobs:
echo "One of the ci-matrix jobs failed"
exit 1
fi
echo "All steps completed successfully"
echo "All steps completed successfully"
29 changes: 29 additions & 0 deletions __tests__/setupTestsReact.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,32 @@ Object.defineProperty(window, 'matchMedia', {
dispatchEvent: jest.fn(),
})),
});

const mockIntersectionObserver = jest.fn((callback, options) => {
return {
root: options?.root,
rootMargin: options?.rootMargin,
thresholds: options?.threshold,
observe: jest.fn(),
unobserve: jest.fn(),
disconnect: jest.fn(),
takeRecords: jest.fn(() => []),
trigger: (entries) => {
callback(entries, mockIntersectionObserver);
},
};
});
global.IntersectionObserver = mockIntersectionObserver;
const mockResizeObserver = jest.fn((callback) => {
return {
observe: jest.fn(),
unobserve: jest.fn(),
disconnect: jest.fn(),
takeRecords: jest.fn(() => []),
getClientRects: jest.fn(() => []),
trigger: (entries) => {
callback(entries, mockResizeObserver);
},
};
});
global.ResizeObserver = mockResizeObserver;
2 changes: 2 additions & 0 deletions jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export const baseConfigFor = (project: string, testExtension: string): Config =>
'^testsutil(/.+)?': '<rootDir>/testsutil$1',
'monaco-editor': '<rootDir>/__mocks__/monaco-editor.ts',
'package.json': '<rootDir>/__mocks__/packagejson.ts',
'^clipboard-polyfill': '<rootDir>/node_modules/@atlaskit/editor-common/dist/cjs/clipboard/index.js',
},

testMatch: [`**/*.test.${testExtension}`],
Expand All @@ -46,6 +47,7 @@ export const baseConfigFor = (project: string, testExtension: string): Config =>
'merge-anything',
'is-what/',
'axios-curlirize/',
'clipboard-polyfill/',
),

collectCoverage: true,
Expand Down
13,618 changes: 12,262 additions & 1,356 deletions package-lock.json

Large diffs are not rendered by default.

37 changes: 37 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1446,6 +1446,7 @@
}
},
"dependencies": {
"@atlaskit/adf-utils": "^19.21.3",
"@atlaskit/analytics-next": "^11.1.1",
"@atlaskit/avatar": "^25.1.12",
"@atlaskit/avatar-group": "^12.2.2",
Expand All @@ -1454,15 +1455,23 @@
"@atlaskit/checkbox": "^17.1.11",
"@atlaskit/comment": "^13.0.20",
"@atlaskit/css": "^0.12.3",
"@atlaskit/css-reset": "^7.3.5",
"@atlaskit/datetime-picker": "^17.0.13",
"@atlaskit/dropdown-menu": "^16.3.8",
"@atlaskit/editor-common": "^109.5.0",
"@atlaskit/editor-core": "^213.0.0",
"@atlaskit/editor-json-transformer": "^8.27.2",
"@atlaskit/editor-plugin-media": "^7.2.6",
"@atlaskit/editor-wikimarkup-transformer": "^11.16.4",
"@atlaskit/feature-gate-js-client": "^5.5.5",
"@atlaskit/form": "^12.2.1",
"@atlaskit/icon": "^27.12.0",
"@atlaskit/icon-lab": "^5.7.0",
"@atlaskit/inline-dialog": "^17.2.6",
"@atlaskit/layering": "^3.0.0",
"@atlaskit/lozenge": "^13.0.8",
"@atlaskit/media-client": "^35.3.5",
"@atlaskit/media-core": "^37.0.0",
"@atlaskit/modal-dialog": "^14.3.4",
"@atlaskit/page": "^14.0.1",
"@atlaskit/page-header": "^12.1.1",
Expand All @@ -1473,6 +1482,7 @@
"@atlaskit/pragmatic-drag-and-drop-live-region": "^1.3.1",
"@atlaskit/pragmatic-drag-and-drop-react-drop-indicator": "^3.2.5",
"@atlaskit/radio": "^8.3.0",
"@atlaskit/renderer": "123.0.0",
"@atlaskit/section-message": "^8.5.1",
"@atlaskit/select": "^21.2.6",
"@atlaskit/spinner": "^19.0.3",
Expand Down Expand Up @@ -1596,6 +1606,7 @@
"@vscode/vsce": "^3.6.0",
"ajv": "^8.17.1",
"ajv-formats": "^3.0.1",
"audit-ci": "^7.1.0",
"autoprefixer": "^10.4.20",
"concurrently": "^9.1.2",
"css-loader": "^7.1.2",
Expand Down Expand Up @@ -1625,6 +1636,7 @@
"postcss-loader": "^8.1.1",
"postcss-preset-env": "^10.2.0",
"prettier": "^3.5.3",
"process": "^0.11.10",
"source-map-loader": "^5.0.0",
"terser-webpack-plugin": "^5.3.0",
"ts-jest": "^29.4.0",
Expand All @@ -1644,6 +1656,31 @@
},
"react-scrolllock": {
"react": "^18.3.1"
},
"@atlaskit/icon-priority": {
"react": "^18.3.1"
},
"react-intl-next": {
"typescript": "^5.8.3"
},
"@atlaskit/code": {
"refractor": "^4.6.1"
},
"@atlaskit/teams-client": {
"@sentry/browser": "^7.119.2"
},
"@atlaskit/editor-common": {
"@sentry/browser": "^7.119.2",
"@atlaskit/media-viewer": "^52.4.20"
},
"fetch-mock": {
"path-to-regexp": "^3.2.0"
},
"react-loosely-lazy": {
"react": "^18.3.1"
},
"react-lazily-render": {
"react": "^18.3.1"
}
},
"packageManager": "[email protected]+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
Expand Down
2 changes: 1 addition & 1 deletion resources/html/reactView.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

<meta
http-equiv="Content-Security-Policy"
content="default-src https://api.atlassian.com ; img-src data: {{cspSource}} http: https: blob:; object-src data:; script-src {{cspSource}};style-src {{cspSource}} 'unsafe-inline' blob: http: https: data:;"
content="default-src https://api.atlassian.com; connect-src {{cspSource}} https://api.media.atlassian.com http: https: ws: wss: data: blob:; img-src data: {{cspSource}} http: https: blob:; object-src data:; script-src {{cspSource}};style-src {{cspSource}} 'unsafe-inline' blob: http: https: data:;"
/>
</head>

Expand Down
2 changes: 1 addition & 1 deletion resources/html/reactWebview.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<link rel="stylesheet" type="text/css" href="{{styleUri}}" />
<meta
http-equiv="Content-Security-Policy"
content="default-src https://api.atlassian.com ; img-src data: {{cspSource}} http: https: blob:; object-src data:; script-src {{cspSource}}; style-src {{cspSource}} 'unsafe-inline' blob: http: https: data:; font-src {{cspSource}} blob: http: https: data:;"
content="default-src https://api.atlassian.com; connect-src {{cspSource}} https://api.media.atlassian.com http: https: ws: wss: data: blob:; img-src data: {{cspSource}} http: https: blob:; object-src data:; script-src {{cspSource}}; style-src {{cspSource}} 'unsafe-inline' blob: http: https: data:; font-src {{cspSource}} blob: http: https: data:;"
/>
</head>

Expand Down
4 changes: 2 additions & 2 deletions src/atlclients/strategyData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export class OAuthStrategyData {
accessibleResourcesURL: 'https://api.atlassian.com/oauth/token/accessible-resources',
callbackURL: remoteAuthConfig.callbackURL,
apiURL: 'api.atlassian.com',
scope: 'read:jira-user read:jira-work write:jira-work offline_access manage:jira-project',
scope: 'read:jira-user read:jira-work write:jira-work offline_access manage:jira-project read:media-api write:media-api',
authParams: {
audience: 'api.atlassian.com',
prompt: 'consent',
Expand All @@ -135,7 +135,7 @@ export class OAuthStrategyData {
accessibleResourcesURL: 'https://api.atlassian.com/oauth/token/accessible-resources',
callbackURL: 'http://127.0.0.1:31415/' + OAuthProvider.JiraCloud,
apiURL: 'api.atlassian.com',
scope: 'read:jira-user read:jira-work write:jira-work offline_access manage:jira-project',
scope: 'read:jira-user read:jira-work write:jira-work offline_access manage:jira-project read:media-api write:media-api',
authParams: {
audience: 'api.atlassian.com',
prompt: 'consent',
Expand Down
2 changes: 1 addition & 1 deletion src/util/features.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
export enum Features {
EnableErrorTelemetry = 'atlascode-send-error-telemetry',
JiraRichText = 'atlascode-jira-rte',
AtlassianNotifications = 'atlascode-atlassian-notifications-v2',
StartWorkV3 = 'atlascode-start-work-v3',
RovoDevEnabled = 'rovo_dev_ff',
UseNewAuthFlow = 'atlascode-use-new-auth-flow',
EnableAiSuggestions = 'atlascode-enable-ai-suggestions',
AtlaskitEditor = 'atlascode-use-new-atlaskit-editor',
}

export const enum Experiments {
Expand Down
8 changes: 7 additions & 1 deletion src/webviews/abstractWebview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ export abstract class AbstractReactWebview implements ReactWebview {
this._panel.reveal(column ? column : ViewColumn.Active); // , false);
}

this.fireFeatureGates([Features.JiraRichText]);
// The webview might not be ready at this point; see getFeatureFlags usage in `onMessageReceived`
this.fireFeatureGates([Features.AtlaskitEditor]);
this.fireExperimentGates([]);
this.fireAdditionalSettings({
rovoDevEnabled: Container.isRovoDevEnabled,
Expand Down Expand Up @@ -234,6 +235,11 @@ export abstract class AbstractReactWebview implements ReactWebview {
Container.pmfStats.touchSurveyed();
return true;
}
case 'getFeatureFlags': {
// Ensures the page is rendered and AbstractIssueEditorPage added listener for FF
this.fireFeatureGates([Features.AtlaskitEditor]);
this.fireExperimentGates([]);
}
}
}

Expand Down
80 changes: 80 additions & 0 deletions src/webviews/components/AdfAwareContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { WikiMarkupTransformer } from '@atlaskit/editor-wikimarkup-transformer';
import { ADFEncoder, ReactRenderer } from '@atlaskit/renderer';
import React from 'react';
// eslint-disable-next-line import/no-extraneous-dependencies
import { IntlProvider } from 'react-intl-next';

interface AdfAwareContentProps {
content: any;
fetchImage: (url: string) => Promise<string>;
getMediaAuth?: () => Promise<{ token: string; clientId?: string; baseUrl?: string }>;
}

/**
* Smart component that detects and renders wiki markup
*/
export const AdfAwareContent: React.FC<AdfAwareContentProps> = ({ content, fetchImage, getMediaAuth }) => {
try {
const buildMedia = () => {
if (!getMediaAuth) {
return undefined as any;
}
const provider = Promise.resolve({
uploadMediaClientConfig: {
authProvider: async () => {
const auth = await getMediaAuth();
return {
token: auth.token,
clientId: auth.clientId,
baseUrl: auth.baseUrl ?? 'https://api.media.atlassian.com',
} as any;
},
},
viewMediaClientConfig: {
authProvider: async () => {
const auth = await getMediaAuth();
return {
token: auth.token,
clientId: auth.clientId,
baseUrl: auth.baseUrl ?? 'https://api.media.atlassian.com',
} as any;
},
},
});
return { provider, featureFlags: { mediaInline: true }, allowMediaSingle: true } as any;
};

// If ADF object passed directly
if (content && typeof content === 'object' && content.type === 'doc') {
return (
<IntlProvider locale="en">
<ReactRenderer data-test-id="adf-renderer" document={content} media={buildMedia()} />
</IntlProvider>
);
}

// If ADF JSON string
if (typeof content === 'string') {
const parsed = JSON.parse(content);
if (parsed && parsed.type === 'doc') {
return (
<IntlProvider locale="en">
<ReactRenderer data-test-id="adf-renderer" document={parsed} media={buildMedia()} />
</IntlProvider>
);
}
}

// Treat as wiki markup → ADF
const adfEncoder = new ADFEncoder((schema) => new WikiMarkupTransformer(schema));
const document = adfEncoder.encode(typeof content === 'string' ? content : '');
return (
<IntlProvider locale="en">
<ReactRenderer data-test-id="adf-renderer" document={document} media={buildMedia()} />
</IntlProvider>
);
} catch (error) {
console.error('Failed to render content, falling back to text:', error);
return <p>{typeof content === 'string' ? content : ''}</p>;
}
};
Loading