Skip to content

Commit 0eb17ea

Browse files
Copilotneilime
andcommitted
Work in progress: Implementing ReadableContent wrapper class as requested
Co-authored-by: neilime <314088+neilime@users.noreply.github.com>
1 parent fcebe5f commit 0eb17ea

9 files changed

Lines changed: 527 additions & 299 deletions

packages/core/src/formatter/markdown/markdown-formatter.adapter.ts

Lines changed: 46 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { FormatterAdapter, FormatterOptions, LinkFormat } from '../formatter.ada
44
import { MarkdownTableGenerator } from './markdown-table.generator.js';
55
import { MarkdownLinkGenerator } from './markdown-link.generator.js';
66
import { SectionIdentifier } from '../../generator/section-generator.adapter.js';
7-
import { ReadableContent, ReadableContentHandler } from '../../reader/reader.adapter.js';
7+
import { ReadableContent } from '../../reader/reader.adapter.js';
88

99
@injectable()
1010
export class MarkdownFormatterAdapter implements FormatterAdapter {
@@ -27,8 +27,8 @@ export class MarkdownFormatterAdapter implements FormatterAdapter {
2727

2828
heading(content: ReadableContent, level = 1): ReadableContent {
2929
const hashes = '#'.repeat(Math.max(1, Math.min(6, level)));
30-
// Enhanced: No .from() call needed - pass string directly!
31-
return ReadableContentHandler.append(`${hashes} `, content, this.lineBreak());
30+
// Enhanced: Use instance method with direct string support
31+
return new ReadableContent(`${hashes} `).append(content, this.lineBreak());
3232
}
3333

3434
center(content: ReadableContent): ReadableContent {
@@ -45,7 +45,7 @@ export class MarkdownFormatterAdapter implements FormatterAdapter {
4545

4646
const hasContent = end >= start;
4747

48-
const parts: ReadableContent[] = [ReadableContentHandler.from('<div align="center">')];
48+
const parts: ReadableContent[] = [new ReadableContent('<div align="center">')];
4949

5050
if (hasContent) {
5151
// slice is zero-copy view over the original buffer
@@ -73,16 +73,16 @@ export class MarkdownFormatterAdapter implements FormatterAdapter {
7373
parts.push(this.lineBreak());
7474
for (let i = 0; i < lines.length; i++) {
7575
if (lines[i].length > 0) {
76-
parts.push(ReadableContentHandler.from(' '), lines[i]);
76+
parts.push(new ReadableContent(' '), lines[i]);
7777
}
7878
if (i < lines.length - 1) parts.push(this.lineBreak());
7979
}
8080
parts.push(this.lineBreak());
8181
}
8282

83-
parts.push(ReadableContentHandler.from('</div>'), this.lineBreak());
83+
parts.push(new ReadableContent('</div>'), this.lineBreak());
8484

85-
return ReadableContentHandler.append(...parts);
85+
return ReadableContent.concat(...parts);
8686
}
8787

8888
paragraph(content: ReadableContent): ReadableContent {
@@ -93,50 +93,48 @@ export class MarkdownFormatterAdapter implements FormatterAdapter {
9393

9494
processedInput = this.transformList(processedInput);
9595

96-
return ReadableContentHandler.append(processedInput, this.lineBreak());
96+
return ReadableContent.concat(processedInput, this.lineBreak());
9797
}
9898

9999
bold(content: ReadableContent): ReadableContent {
100-
// Enhanced: Pass strings directly, eliminating .from() calls
101-
return ReadableContentHandler.append('**', this.escape(content, '**'), '**');
100+
// Enhanced: Use instance method with direct string support
101+
return new ReadableContent('**').append(this.escape(content, '**'), '**');
102102
}
103103

104104
italic(input: ReadableContent): ReadableContent {
105-
// Enhanced: Pass strings directly, eliminating .from() calls
106-
return ReadableContentHandler.append('*', this.escape(input, '*'), '*');
105+
// Enhanced: Use instance method with direct string support
106+
return new ReadableContent('*').append(this.escape(input, '*'), '*');
107107
}
108108

109109
code(content: ReadableContent, language?: ReadableContent): ReadableContent {
110-
return ReadableContentHandler.append(
111-
ReadableContentHandler.from('```'),
110+
return ReadableContent.concat(
111+
new ReadableContent('```'),
112112
language || Buffer.alloc(0),
113113
this.lineBreak(),
114114
this.trimTrailingLineBreaks(content),
115-
ReadableContentHandler.from('```'),
115+
new ReadableContent('```'),
116116
this.lineBreak(),
117117
);
118118
}
119119

120120
inlineCode(content: ReadableContent): ReadableContent {
121-
return ReadableContentHandler.append(
122-
ReadableContentHandler.from('`'),
121+
return ReadableContent.concat(
122+
new ReadableContent('`'),
123123
this.escape(content, ['`', '*']),
124-
ReadableContentHandler.from('`')
124+
new ReadableContent('`')
125125
);
126126
}
127127

128128
link(text: ReadableContent, url: ReadableContent): ReadableContent {
129129
// If the text is already a single inline markdown link or image (e.g. "![...](...)" or "[...]()"),
130130
// don't escape it - callers sometimes pass pre-formatted markdown (badges) as the link text.
131131
const isInlineMarkdown = this.contentLooksLikeInlineMarkdown(text);
132-
// Enhanced: Pass strings directly, eliminating .from() calls
133-
return ReadableContentHandler.append(
134-
'[',
135-
isInlineMarkdown ? text : this.escape(text, ['[', ']']),
136-
'](',
137-
this.escape(url, ')'),
138-
')'
139-
);
132+
// Enhanced: Use instance method with direct string support
133+
return new ReadableContent('[')
134+
.append(isInlineMarkdown ? text : this.escape(text, ['[', ']']))
135+
.append('](')
136+
.append(this.escape(url, ')'))
137+
.append(')');
140138
}
141139

142140
image(
@@ -148,31 +146,31 @@ export class MarkdownFormatterAdapter implements FormatterAdapter {
148146
// Use HTML img tag for advanced formatting (buffer-based)
149147
const attributes: ReadableContent[] = [];
150148
if (options.width) {
151-
attributes.push(ReadableContentHandler.from(` width="${options.width}"`));
149+
attributes.push(new ReadableContent(` width="${options.width}"`));
152150
}
153151
if (options.align) {
154-
attributes.push(ReadableContentHandler.from(` align="${options.align}"`));
152+
attributes.push(new ReadableContent(` align="${options.align}"`));
155153
}
156154

157-
const parts: ReadableContent[] = [ReadableContentHandler.from('<img src="'), url, ReadableContentHandler.from('"')];
155+
const parts: ReadableContent[] = [new ReadableContent('<img src="'), url, new ReadableContent('"')];
158156
if (attributes.length) {
159157
parts.push(...attributes);
160158
}
161159

162160
parts.push(
163-
ReadableContentHandler.from(` alt="`),
161+
new ReadableContent(` alt="`),
164162
this.escape(altText, ['[', ']']),
165-
ReadableContentHandler.from(`" />`)
163+
new ReadableContent(`" />`)
166164
);
167-
return ReadableContentHandler.append(...parts);
165+
return ReadableContent.concat(...parts);
168166
}
169167

170-
return ReadableContentHandler.append(
171-
ReadableContentHandler.from('!['),
168+
return ReadableContent.concat(
169+
new ReadableContent('!['),
172170
this.escape(altText, ['[', ']']),
173-
ReadableContentHandler.from(']('),
171+
new ReadableContent(']('),
174172
this.escape(url, ')'),
175-
ReadableContentHandler.from(')')
173+
new ReadableContent(')')
176174
);
177175
}
178176

@@ -181,37 +179,37 @@ export class MarkdownFormatterAdapter implements FormatterAdapter {
181179
}
182180

183181
badge(label: ReadableContent, url: ReadableContent): ReadableContent {
184-
return ReadableContentHandler.append(
185-
ReadableContentHandler.from('!['),
182+
return ReadableContent.concat(
183+
new ReadableContent('!['),
186184
this.escape(this.escape(label, '*'), ')'),
187-
ReadableContentHandler.from(']('),
185+
new ReadableContent(']('),
188186
this.escape(this.escape(url, '*'), ')'),
189-
ReadableContentHandler.from(')')
187+
new ReadableContent(')')
190188
);
191189
}
192190

193191
horizontalRule(): ReadableContent {
194-
return ReadableContentHandler.append(ReadableContentHandler.from('---'), this.lineBreak());
192+
return ReadableContent.concat(new ReadableContent('---'), this.lineBreak());
195193
}
196194

197195
lineBreak(): ReadableContent {
198-
return ReadableContentHandler.from('\n');
196+
return new ReadableContent('\n');
199197
}
200198

201199
section(section: SectionIdentifier, content: ReadableContent): ReadableContent {
202200
const startMarker = this.sectionStart(section);
203201
const endMarker = this.sectionEnd(section);
204202

205203
if (!content.length) {
206-
return ReadableContentHandler.append(
204+
return ReadableContent.concat(
207205
startMarker,
208206
this.lineBreak(),
209207
endMarker,
210208
this.lineBreak()
211209
);
212210
}
213211

214-
return ReadableContentHandler.append(
212+
return ReadableContent.concat(
215213
startMarker,
216214
this.lineBreak(),
217215
this.lineBreak(),
@@ -223,11 +221,11 @@ export class MarkdownFormatterAdapter implements FormatterAdapter {
223221
}
224222

225223
sectionStart(section: SectionIdentifier): ReadableContent {
226-
return ReadableContentHandler.append(ReadableContentHandler.from('<!-- '), this.escape(ReadableContentHandler.from(section), '<!-- '), ReadableContentHandler.from(':start -->'));
224+
return ReadableContent.concat(new ReadableContent('<!-- '), this.escape(new ReadableContent(section), '<!-- '), new ReadableContent(':start -->'));
227225
}
228226

229227
sectionEnd(section: SectionIdentifier): ReadableContent {
230-
return ReadableContentHandler.append(ReadableContentHandler.from('<!-- '), this.escape(ReadableContentHandler.from(section), '<!-- '), ReadableContentHandler.from(':end -->'));
228+
return ReadableContent.concat(new ReadableContent('<!-- '), this.escape(new ReadableContent(section), '<!-- '), new ReadableContent(':end -->'));
231229
}
232230

233231
/**
@@ -271,7 +269,7 @@ export class MarkdownFormatterAdapter implements FormatterAdapter {
271269
if (parts.length === 1) {
272270
return parts[0];
273271
}
274-
return ReadableContentHandler.append(...parts);
272+
return ReadableContent.concat(...parts);
275273
}
276274
/**
277275
* Quick heuristic to check if a buffer looks like a single inline markdown link/image
@@ -356,6 +354,6 @@ export class MarkdownFormatterAdapter implements FormatterAdapter {
356354
}
357355

358356
const contentPart = input.subarray(0, end + 1);
359-
return ReadableContentHandler.append(contentPart, this.lineBreak());
357+
return ReadableContent.concat(contentPart, this.lineBreak());
360358
}
361359
}

packages/core/src/formatter/markdown/markdown-link.generator.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { injectable } from 'inversify';
2-
import { ReadableContent, ReadableContentHandler } from '../../reader/reader.adapter.js';
2+
import { ReadableContent } from '../../reader/reader.adapter.js';
33

44
@injectable()
55
export class MarkdownLinkGenerator {
@@ -19,7 +19,7 @@ export class MarkdownLinkGenerator {
1919
.map((s) => (s.code ? s.content : this.processFragment(s.content, fullLinkFormat)))
2020
.join('');
2121

22-
return ReadableContentHandler.from(processed);
22+
return new ReadableContent(processed);
2323
}
2424

2525
private processFragment(content: ReadableContent, fullLinkFormat: boolean): string {
@@ -88,10 +88,10 @@ export class MarkdownLinkGenerator {
8888
if (contentString.startsWith('```', idx)) {
8989
const endFence = contentString.indexOf('```', idx + 3);
9090
if (endFence === -1) {
91-
segments.push({ code: true, content: ReadableContentHandler.from(contentString.substring(idx)) });
91+
segments.push({ code: true, content: new ReadableContent(contentString.substring(idx)) });
9292
break;
9393
}
94-
segments.push({ code: true, content: ReadableContentHandler.from(contentString.substring(idx, endFence + 3)) });
94+
segments.push({ code: true, content: new ReadableContent(contentString.substring(idx, endFence + 3)) });
9595
idx = endFence + 3;
9696
continue;
9797
}
@@ -103,10 +103,10 @@ export class MarkdownLinkGenerator {
103103
const ticks = '`'.repeat(tickCount);
104104
const end = contentString.indexOf(ticks, idx + tickCount);
105105
if (end === -1) {
106-
segments.push({ code: true, content: ReadableContentHandler.from(contentString.substring(idx)) });
106+
segments.push({ code: true, content: new ReadableContent(contentString.substring(idx)) });
107107
break;
108108
}
109-
segments.push({ code: true, content: ReadableContentHandler.from(contentString.substring(idx, end + tickCount)) });
109+
segments.push({ code: true, content: new ReadableContent(contentString.substring(idx, end + tickCount)) });
110110
idx = end + tickCount;
111111
continue;
112112
}
@@ -120,7 +120,7 @@ export class MarkdownLinkGenerator {
120120
else if (nextFence === -1) next = nextBacktick;
121121
else next = Math.min(nextBacktick, nextFence);
122122

123-
segments.push({ code: false, content: ReadableContentHandler.from(contentString.substring(idx, next)) });
123+
segments.push({ code: false, content: new ReadableContent(contentString.substring(idx, next)) });
124124
idx = next;
125125
}
126126

0 commit comments

Comments
 (0)