atl-fetch 1.1.0 → 1.2.1

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/README.md CHANGED
@@ -25,7 +25,18 @@ Atlassian Cloud(Jira / Confluence)から情報を取得する Node.js CLI
25
25
  - Node.js 22.0.0 以上
26
26
  - pnpm(推奨)または npm
27
27
 
28
- ## インストール
28
+ ## 使い方
29
+
30
+ ### npx で即時実行(インストール不要)
31
+
32
+ ```bash
33
+ # 環境変数を設定して実行
34
+ ATLASSIAN_EMAIL="your-email@example.com" \
35
+ ATLASSIAN_API_TOKEN="your-api-token" \
36
+ npx atl-fetch https://your-domain.atlassian.net/browse/PROJECT-123
37
+ ```
38
+
39
+ ### グローバルインストール
29
40
 
30
41
  ```bash
31
42
  # npm
@@ -50,21 +61,23 @@ API トークンは [Atlassian Account Settings](https://id.atlassian.com/manage
50
61
 
51
62
  ```bash
52
63
  # Jira Issue を取得
53
- atl-fetch https://your-domain.atlassian.net/browse/PROJECT-123
64
+ npx atl-fetch https://your-domain.atlassian.net/browse/PROJECT-123
54
65
 
55
66
  # Confluence ページを取得
56
- atl-fetch https://your-domain.atlassian.net/wiki/spaces/SPACE/pages/123456/Page+Title
67
+ npx atl-fetch https://your-domain.atlassian.net/wiki/spaces/SPACE/pages/123456/Page+Title
57
68
 
58
69
  # Markdown 形式で出力
59
- atl-fetch https://your-domain.atlassian.net/browse/PROJECT-123 --format markdown
70
+ npx atl-fetch https://your-domain.atlassian.net/browse/PROJECT-123 --format markdown
60
71
 
61
72
  # 添付ファイルをダウンロード
62
- atl-fetch https://your-domain.atlassian.net/browse/PROJECT-123 --download --dir ./output
73
+ npx atl-fetch https://your-domain.atlassian.net/browse/PROJECT-123 --download --dir ./output
63
74
 
64
75
  # ファイルに保存(リダイレクト)
65
- atl-fetch https://your-domain.atlassian.net/browse/PROJECT-123 > result.json
76
+ npx atl-fetch https://your-domain.atlassian.net/browse/PROJECT-123 > result.json
66
77
  ```
67
78
 
79
+ **Note**: グローバルインストール済みの場合は `npx` を省略して `atl-fetch` として実行できます。
80
+
68
81
  ## CLI オプション
69
82
 
70
83
  | オプション | 短縮形 | 説明 | デフォルト |
@@ -88,7 +101,7 @@ atl-fetch https://your-domain.atlassian.net/browse/PROJECT-123 > result.json
88
101
  認証情報の設定状態を確認します。
89
102
 
90
103
  ```bash
91
- atl-fetch auth check
104
+ npx atl-fetch auth check
92
105
  ```
93
106
 
94
107
  出力例(設定済み):
@@ -3,7 +3,7 @@ import { fetchConfluencePage } from '../confluence/confluence-service.js';
3
3
  import { fetchJiraIssue } from '../jira/jira-service.js';
4
4
  import { formatConfluencePage, formatJiraIssue, writeToFile } from '../output/output-service.js';
5
5
  import { saveConfluencePage, saveConfluenceVersions, saveJiraIssue } from '../storage/storage-service.js';
6
- import { convertAdfToPlainText, convertStorageFormatToPlainText } from '../text-converter/text-converter.js';
6
+ import { convertStorageFormatToPlainText } from '../text-converter/text-converter.js';
7
7
  import { parseUrl } from '../url-parser/url-parser.js';
8
8
  /**
9
9
  * Jira エラーを FetchError に変換する
@@ -230,15 +230,14 @@ export async function fetchAndSave(url, options) {
230
230
  return err(mapJiraErrorToFetchError(issueResult.error));
231
231
  }
232
232
  const issue = issueResult.value;
233
- // ADF をプレーンテキストに変換
234
- const descriptionPlainText = issue.description !== null ? convertAdfToPlainText(issue.description) : null;
235
233
  // Jira Issue をディレクトリ構造で保存
234
+ // description は ADF 形式で保存、descriptionPlainText は後方互換性のため維持
236
235
  const saveResult = await saveJiraIssue({
237
236
  attachments: issue.attachments,
238
237
  changelog: issue.changelog,
239
238
  comments: issue.comments,
240
- description: issue.description,
241
- descriptionPlainText,
239
+ description: issue.descriptionAdf,
240
+ descriptionPlainText: issue.description,
242
241
  key: issue.key,
243
242
  summary: issue.summary,
244
243
  }, {
@@ -108,6 +108,7 @@ function mapApiCommentToJiraComment(apiComment) {
108
108
  return {
109
109
  author: apiComment.author.displayName,
110
110
  body: extractTextFromAdf(apiComment.body),
111
+ bodyAdf: apiComment.body,
111
112
  created: apiComment.created,
112
113
  id: apiComment.id,
113
114
  updated: apiComment.updated,
@@ -254,6 +255,7 @@ export async function fetchJiraIssue(organization, issueKey) {
254
255
  changelog: (apiResponse.changelog?.histories ?? []).map(mapApiChangelogEntryToJiraChangelogEntry),
255
256
  comments: (apiResponse.fields.comment?.comments ?? []).map(mapApiCommentToJiraComment),
256
257
  description: apiResponse.fields.description ? extractTextFromAdf(apiResponse.fields.description) : null,
258
+ descriptionAdf: apiResponse.fields.description,
257
259
  key: apiResponse.key,
258
260
  summary: apiResponse.fields.summary,
259
261
  };
@@ -16,9 +16,11 @@ import type { ConfluenceSaveData, ConfluenceSaveResult, ConfluenceStorageOptions
16
16
  * ├── manifest.json # 取得メタデータ
17
17
  * ├── issue.json # Issue 全データ(JSON 形式)
18
18
  * ├── description.txt # 説明文のプレーンテキスト
19
- * ├── content.md # Markdown 形式
20
- * ├── changelog.json # 変更履歴
21
- * ├── comments.json # コメント一覧
19
+ * ├── content.md # Markdown 形式(Description + Attachments)
20
+ * ├── comments.md # コメント一覧(Markdown 形式)
21
+ * ├── changelog.md # 変更履歴(Markdown 形式)
22
+ * ├── changelog.json # 変更履歴(JSON 形式)
23
+ * ├── comments.json # コメント一覧(JSON 形式)
22
24
  * ├── attachments.json # 添付ファイル一覧メタデータ
23
25
  * └── attachments/ # 添付ファイル実体
24
26
  * └── {id}_{filename}
@@ -10,7 +10,7 @@ import { ensureDir, writeFileContent } from '../../ports/file/file-port.js';
10
10
  import { downloadConfluenceAttachment } from '../confluence/confluence-service.js';
11
11
  import { diffText } from '../diff/diff-service.js';
12
12
  import { downloadJiraAttachment } from '../jira/jira-service.js';
13
- import { convertStorageFormatToMarkdown } from '../text-converter/text-converter.js';
13
+ import { convertAdfToMarkdown, convertStorageFormatToMarkdown } from '../text-converter/text-converter.js';
14
14
  /**
15
15
  * 現在時刻を ISO 8601 形式で取得する
16
16
  *
@@ -51,9 +51,11 @@ const createJiraManifest = (data, options, attachmentResults) => {
51
51
  * ├── manifest.json # 取得メタデータ
52
52
  * ├── issue.json # Issue 全データ(JSON 形式)
53
53
  * ├── description.txt # 説明文のプレーンテキスト
54
- * ├── content.md # Markdown 形式
55
- * ├── changelog.json # 変更履歴
56
- * ├── comments.json # コメント一覧
54
+ * ├── content.md # Markdown 形式(Description + Attachments)
55
+ * ├── comments.md # コメント一覧(Markdown 形式)
56
+ * ├── changelog.md # 変更履歴(Markdown 形式)
57
+ * ├── changelog.json # 変更履歴(JSON 形式)
58
+ * ├── comments.json # コメント一覧(JSON 形式)
57
59
  * ├── attachments.json # 添付ファイル一覧メタデータ
58
60
  * └── attachments/ # 添付ファイル実体
59
61
  * └── {id}_{filename}
@@ -150,7 +152,7 @@ export const saveJiraIssue = async (data, options) => {
150
152
  path: descPath,
151
153
  });
152
154
  }
153
- // content.md を保存(Markdown 形式)
155
+ // content.md を保存(Markdown 形式:Description + Attachments)
154
156
  const markdownContent = formatJiraIssueAsMarkdown(data, attachmentResults);
155
157
  const markdownPath = join(issueDir, 'content.md');
156
158
  const markdownWriteResult = await writeFileContent(markdownPath, markdownContent);
@@ -161,6 +163,28 @@ export const saveJiraIssue = async (data, options) => {
161
163
  path: markdownPath,
162
164
  });
163
165
  }
166
+ // comments.md を保存(Markdown 形式)
167
+ const commentsMarkdownContent = formatCommentsAsMarkdown(data, attachmentResults);
168
+ const commentsMarkdownPath = join(issueDir, 'comments.md');
169
+ const commentsMarkdownWriteResult = await writeFileContent(commentsMarkdownPath, commentsMarkdownContent);
170
+ if (commentsMarkdownWriteResult.isErr()) {
171
+ return err({
172
+ kind: 'FILE_WRITE_FAILED',
173
+ message: `comments.md の書き込みに失敗しました: ${commentsMarkdownWriteResult.error.message}`,
174
+ path: commentsMarkdownPath,
175
+ });
176
+ }
177
+ // changelog.md を保存(Markdown 形式)
178
+ const changelogMarkdownContent = formatChangelogAsMarkdown(data);
179
+ const changelogMarkdownPath = join(issueDir, 'changelog.md');
180
+ const changelogMarkdownWriteResult = await writeFileContent(changelogMarkdownPath, changelogMarkdownContent);
181
+ if (changelogMarkdownWriteResult.isErr()) {
182
+ return err({
183
+ kind: 'FILE_WRITE_FAILED',
184
+ message: `changelog.md の書き込みに失敗しました: ${changelogMarkdownWriteResult.error.message}`,
185
+ path: changelogMarkdownPath,
186
+ });
187
+ }
164
188
  // changelog.json を保存
165
189
  const changelogPath = join(issueDir, 'changelog.json');
166
190
  const changelogWriteResult = await writeFileContent(changelogPath, JSON.stringify(data.changelog, null, 2));
@@ -199,54 +223,38 @@ export const saveJiraIssue = async (data, options) => {
199
223
  /**
200
224
  * Jira Issue を Markdown 形式にフォーマットする(ファイル保存用)
201
225
  *
226
+ * ADF (Atlassian Document Format) を Markdown に変換して保存する。
227
+ * Confluence と同様に構造を保持した Markdown を生成する。
228
+ *
202
229
  * @param data 保存データ
203
230
  * @param attachmentResults 添付ファイルのダウンロード結果
204
231
  * @returns Markdown 文字列
205
232
  */
206
233
  const formatJiraIssueAsMarkdown = (data, attachmentResults) => {
234
+ // 添付ファイル ID → savedPath のマッピングを生成
235
+ const attachmentPaths = {};
236
+ for (const att of attachmentResults) {
237
+ if (att.status === 'success' && att.savedPath !== undefined) {
238
+ attachmentPaths[att.id] = att.savedPath;
239
+ }
240
+ }
207
241
  const lines = [];
208
242
  // Title
209
243
  lines.push(`# ${data.key}`);
210
244
  lines.push('');
211
245
  lines.push(`**${data.summary}**`);
212
246
  lines.push('');
213
- // Description
247
+ // Description - ADF を Markdown に変換
214
248
  lines.push('## Description');
215
249
  lines.push('');
216
- lines.push(data.descriptionPlainText ?? '(No description)');
217
- lines.push('');
218
- // Comments
219
- lines.push('## Comments');
220
- lines.push('');
221
- if (data.comments.length === 0) {
222
- lines.push('No comments');
250
+ if (data.description !== null && data.description !== undefined) {
251
+ const descriptionMarkdown = convertAdfToMarkdown(data.description, attachmentPaths);
252
+ lines.push(descriptionMarkdown || '(No description)');
223
253
  }
224
254
  else {
225
- for (const comment of data.comments) {
226
- lines.push(`### ${comment.author} (${comment.created})`);
227
- lines.push('');
228
- lines.push(comment.body);
229
- lines.push('');
230
- }
255
+ lines.push('(No description)');
231
256
  }
232
- // Changelog
233
- lines.push('## Changelog');
234
257
  lines.push('');
235
- if (data.changelog.length === 0) {
236
- lines.push('No changelog');
237
- }
238
- else {
239
- for (const entry of data.changelog) {
240
- lines.push(`### ${entry.author} (${entry.created})`);
241
- lines.push('');
242
- for (const item of entry.items) {
243
- const from = item.fromString ?? '(empty)';
244
- const to = item.toString ?? '(empty)';
245
- lines.push(`- **${item.field}**: ${from} → ${to}`);
246
- }
247
- lines.push('');
248
- }
249
- }
250
258
  // Attachments
251
259
  lines.push('## Attachments');
252
260
  lines.push('');
@@ -272,6 +280,66 @@ const formatJiraIssueAsMarkdown = (data, attachmentResults) => {
272
280
  }
273
281
  return lines.join('\n');
274
282
  };
283
+ /**
284
+ * Jira コメントを Markdown 形式にフォーマットする(ファイル保存用)
285
+ *
286
+ * @param data 保存データ
287
+ * @param attachmentResults 添付ファイルのダウンロード結果
288
+ * @returns Markdown 文字列
289
+ */
290
+ const formatCommentsAsMarkdown = (data, attachmentResults) => {
291
+ // 添付ファイル ID → savedPath のマッピングを生成
292
+ const attachmentPaths = {};
293
+ for (const att of attachmentResults) {
294
+ if (att.status === 'success' && att.savedPath !== undefined) {
295
+ attachmentPaths[att.id] = att.savedPath;
296
+ }
297
+ }
298
+ const lines = [];
299
+ lines.push(`# ${data.key} - Comments`);
300
+ lines.push('');
301
+ if (data.comments.length === 0) {
302
+ lines.push('No comments');
303
+ }
304
+ else {
305
+ for (const comment of data.comments) {
306
+ lines.push(`## ${comment.author} (${comment.created})`);
307
+ lines.push('');
308
+ // コメント本文も ADF 形式なので Markdown に変換
309
+ const commentMarkdown = convertAdfToMarkdown(comment.bodyAdf, attachmentPaths);
310
+ lines.push(commentMarkdown || comment.body);
311
+ lines.push('');
312
+ }
313
+ }
314
+ return lines.join('\n');
315
+ };
316
+ /**
317
+ * Jira 変更履歴を Markdown 形式にフォーマットする(ファイル保存用)
318
+ *
319
+ * @param data 保存データ
320
+ * @returns Markdown 文字列
321
+ */
322
+ const formatChangelogAsMarkdown = (data) => {
323
+ const lines = [];
324
+ lines.push(`# ${data.key} - Changelog`);
325
+ lines.push('');
326
+ if (data.changelog.length === 0) {
327
+ lines.push('No changelog');
328
+ }
329
+ else {
330
+ for (const entry of data.changelog) {
331
+ lines.push(`## ${entry.author} (${entry.created})`);
332
+ lines.push('');
333
+ for (const item of entry.items) {
334
+ const from = item.fromString ?? '(empty)';
335
+ const to = item.toString ?? '(empty)';
336
+ lines.push(`- **${item.field}**: ${from} → ${to}`);
337
+ }
338
+ lines.push('');
339
+ }
340
+ }
341
+ return lines.join('\n');
342
+ };
275
343
  /**
276
344
  * Confluence ページ用の Manifest を生成する
277
345
  *
@@ -735,4 +803,197 @@ if (import.meta.vitest) {
735
803
  });
736
804
  });
737
805
  });
806
+ describe('formatCommentsAsMarkdown (in-source testing)', () => {
807
+ // テストの目的: コメントがない場合に "No comments" が出力されること
808
+ it('Given: コメントがない JiraSaveData, When: formatCommentsAsMarkdown を呼び出す, Then: "No comments" が出力される', () => {
809
+ const data = {
810
+ attachments: [],
811
+ changelog: [],
812
+ comments: [],
813
+ description: null,
814
+ descriptionPlainText: null,
815
+ key: 'TEST-001',
816
+ summary: 'テスト',
817
+ };
818
+ const result = formatCommentsAsMarkdown(data, []);
819
+ expect(result).toContain('# TEST-001 - Comments');
820
+ expect(result).toContain('No comments');
821
+ });
822
+ // テストの目的: コメントが正しくフォーマットされること
823
+ it('Given: コメントを含む JiraSaveData, When: formatCommentsAsMarkdown を呼び出す, Then: コメントが Markdown 形式でフォーマットされる', () => {
824
+ const data = {
825
+ attachments: [],
826
+ changelog: [],
827
+ comments: [
828
+ {
829
+ author: 'TestUser',
830
+ body: 'テストコメント',
831
+ bodyAdf: null, // bodyAdf が null の場合は body が使用される
832
+ created: '2024-01-15T10:30:00.000Z',
833
+ id: 'cmt-1',
834
+ updated: '2024-01-15T10:30:00.000Z',
835
+ },
836
+ ],
837
+ description: null,
838
+ descriptionPlainText: null,
839
+ key: 'TEST-002',
840
+ summary: 'テスト',
841
+ };
842
+ const result = formatCommentsAsMarkdown(data, []);
843
+ expect(result).toContain('# TEST-002 - Comments');
844
+ expect(result).toContain('## TestUser');
845
+ expect(result).toContain('2024-01-15T10:30:00.000Z');
846
+ expect(result).toContain('テストコメント');
847
+ });
848
+ // テストの目的: 複数のコメントが正しくフォーマットされること
849
+ it('Given: 複数のコメントを含む JiraSaveData, When: formatCommentsAsMarkdown を呼び出す, Then: すべてのコメントが Markdown 形式でフォーマットされる', () => {
850
+ const data = {
851
+ attachments: [],
852
+ changelog: [],
853
+ comments: [
854
+ {
855
+ author: 'User1',
856
+ body: 'コメント1',
857
+ bodyAdf: null,
858
+ created: '2024-01-15T10:00:00.000Z',
859
+ id: 'cmt-1',
860
+ updated: '2024-01-15T10:00:00.000Z',
861
+ },
862
+ {
863
+ author: 'User2',
864
+ body: 'コメント2',
865
+ bodyAdf: null,
866
+ created: '2024-01-16T11:00:00.000Z',
867
+ id: 'cmt-2',
868
+ updated: '2024-01-16T11:00:00.000Z',
869
+ },
870
+ ],
871
+ description: null,
872
+ descriptionPlainText: null,
873
+ key: 'TEST-003',
874
+ summary: 'テスト',
875
+ };
876
+ const result = formatCommentsAsMarkdown(data, []);
877
+ expect(result).toContain('## User1');
878
+ expect(result).toContain('## User2');
879
+ expect(result).toContain('コメント1');
880
+ expect(result).toContain('コメント2');
881
+ });
882
+ });
883
+ describe('formatChangelogAsMarkdown (in-source testing)', () => {
884
+ // テストの目的: 変更履歴がない場合に "No changelog" が出力されること
885
+ it('Given: 変更履歴がない JiraSaveData, When: formatChangelogAsMarkdown を呼び出す, Then: "No changelog" が出力される', () => {
886
+ const data = {
887
+ attachments: [],
888
+ changelog: [],
889
+ comments: [],
890
+ description: null,
891
+ descriptionPlainText: null,
892
+ key: 'TEST-001',
893
+ summary: 'テスト',
894
+ };
895
+ const result = formatChangelogAsMarkdown(data);
896
+ expect(result).toContain('# TEST-001 - Changelog');
897
+ expect(result).toContain('No changelog');
898
+ });
899
+ // テストの目的: 変更履歴が正しくフォーマットされること
900
+ it('Given: 変更履歴を含む JiraSaveData, When: formatChangelogAsMarkdown を呼び出す, Then: 変更履歴が Markdown 形式でフォーマットされる', () => {
901
+ const data = {
902
+ attachments: [],
903
+ changelog: [
904
+ {
905
+ author: 'ChangeUser',
906
+ created: '2024-01-15T10:00:00.000Z',
907
+ id: 'cl-1',
908
+ items: [{ field: 'status', fromString: 'Open', toString: 'In Progress' }],
909
+ },
910
+ ],
911
+ comments: [],
912
+ description: null,
913
+ descriptionPlainText: null,
914
+ key: 'TEST-002',
915
+ summary: 'テスト',
916
+ };
917
+ const result = formatChangelogAsMarkdown(data);
918
+ expect(result).toContain('# TEST-002 - Changelog');
919
+ expect(result).toContain('## ChangeUser');
920
+ expect(result).toContain('2024-01-15T10:00:00.000Z');
921
+ expect(result).toContain('**status**');
922
+ expect(result).toContain('Open');
923
+ expect(result).toContain('In Progress');
924
+ });
925
+ // テストの目的: null 値が (empty) として表示されること
926
+ it('Given: fromString が null の変更履歴, When: formatChangelogAsMarkdown を呼び出す, Then: (empty) が表示される', () => {
927
+ const data = {
928
+ attachments: [],
929
+ changelog: [
930
+ {
931
+ author: 'ChangeUser',
932
+ created: '2024-01-15T10:00:00.000Z',
933
+ id: 'cl-1',
934
+ items: [{ field: 'assignee', fromString: null, toString: 'Developer' }],
935
+ },
936
+ ],
937
+ comments: [],
938
+ description: null,
939
+ descriptionPlainText: null,
940
+ key: 'TEST-003',
941
+ summary: 'テスト',
942
+ };
943
+ const result = formatChangelogAsMarkdown(data);
944
+ expect(result).toContain('(empty)');
945
+ expect(result).toContain('Developer');
946
+ });
947
+ // テストの目的: toString が null の場合も (empty) として表示されること
948
+ it('Given: toString が null の変更履歴, When: formatChangelogAsMarkdown を呼び出す, Then: (empty) が表示される', () => {
949
+ const data = {
950
+ attachments: [],
951
+ changelog: [
952
+ {
953
+ author: 'ChangeUser',
954
+ created: '2024-01-15T10:00:00.000Z',
955
+ id: 'cl-1',
956
+ items: [{ field: 'assignee', fromString: 'Developer', toString: null }],
957
+ },
958
+ ],
959
+ comments: [],
960
+ description: null,
961
+ descriptionPlainText: null,
962
+ key: 'TEST-004',
963
+ summary: 'テスト',
964
+ };
965
+ const result = formatChangelogAsMarkdown(data);
966
+ expect(result).toContain('Developer');
967
+ expect(result).toContain('(empty)');
968
+ });
969
+ // テストの目的: 複数の変更項目が正しくフォーマットされること
970
+ it('Given: 複数の変更項目を含む変更履歴, When: formatChangelogAsMarkdown を呼び出す, Then: すべての項目が Markdown 形式でフォーマットされる', () => {
971
+ const data = {
972
+ attachments: [],
973
+ changelog: [
974
+ {
975
+ author: 'ChangeUser',
976
+ created: '2024-01-15T10:00:00.000Z',
977
+ id: 'cl-1',
978
+ items: [
979
+ { field: 'status', fromString: 'Open', toString: 'In Progress' },
980
+ { field: 'priority', fromString: 'Low', toString: 'High' },
981
+ ],
982
+ },
983
+ ],
984
+ comments: [],
985
+ description: null,
986
+ descriptionPlainText: null,
987
+ key: 'TEST-005',
988
+ summary: 'テスト',
989
+ };
990
+ const result = formatChangelogAsMarkdown(data);
991
+ expect(result).toContain('**status**');
992
+ expect(result).toContain('**priority**');
993
+ expect(result).toContain('Open');
994
+ expect(result).toContain('In Progress');
995
+ expect(result).toContain('Low');
996
+ expect(result).toContain('High');
997
+ });
998
+ });
738
999
  }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * ADF(Atlassian Document Format)→ HTML 変換
3
+ *
4
+ * Markdown 変換の中間形式として HTML を生成する
5
+ */
6
+ import type { AdfMark, AdfNode, AttachmentPathMapping } from './types.js';
7
+ /**
8
+ * HTML 特殊文字をエスケープする
9
+ *
10
+ * @param text エスケープ対象の文字列
11
+ * @returns エスケープ済み文字列
12
+ */
13
+ export declare const escapeHtml: (text: string) => string;
14
+ /**
15
+ * ADF マークを HTML タグで囲む
16
+ *
17
+ * @param text 対象のテキスト
18
+ * @param marks 適用するマーク配列
19
+ * @returns マークを適用した HTML
20
+ */
21
+ export declare const applyMarksToHtml: (text: string, marks: readonly AdfMark[]) => string;
22
+ /**
23
+ * ADF ノードを HTML に変換する
24
+ *
25
+ * @param node ADF ノード
26
+ * @param attachmentPaths 添付ファイル ID → ローカルパスのマッピング
27
+ * @returns HTML 文字列
28
+ */
29
+ export declare const convertAdfNodeToHtml: (node: AdfNode, attachmentPaths?: AttachmentPathMapping) => string;
30
+ /**
31
+ * ADF ドキュメントを HTML に変換する
32
+ *
33
+ * @param content ADF ドキュメントのコンテンツ配列
34
+ * @param attachmentPaths 添付ファイル ID → ローカルパスのマッピング
35
+ * @returns HTML 文字列
36
+ */
37
+ export declare const convertAdfContentToHtml: (content: readonly AdfNode[] | undefined, attachmentPaths?: AttachmentPathMapping) => string;