import { _defaults } from './defaults.ts';
import {
cleanUrl,
escape,
} from './helpers.ts';
import { other } from './rules.ts';
import type { MarkedOptions } from './MarkedOptions.ts';
import type { Tokens } from './Tokens.ts';
import type { _Parser } from './Parser.ts';
/**
* Renderer
*/
export class _Renderer {
options: MarkedOptions;
parser!: _Parser; // set by the parser
constructor(options?: MarkedOptions) {
this.options = options || _defaults;
}
space(token: Tokens.Space): string {
return '';
}
code({ text, lang, escaped }: Tokens.Code): string {
const langString = (lang || '').match(other.notSpaceStart)?.[0];
const code = text.replace(other.endingNewline, '') + '\n';
if (!langString) {
return '
'
+ (escaped ? code : escape(code, true))
+ '
\n';
}
return ''
+ (escaped ? code : escape(code, true))
+ '
\n';
}
blockquote({ tokens }: Tokens.Blockquote): string {
const body = this.parser.parse(tokens);
return `\n${body}
\n`;
}
html({ text }: Tokens.HTML | Tokens.Tag) : string {
return text;
}
heading({ tokens, depth }: Tokens.Heading): string {
return `${this.parser.parseInline(tokens)}\n`;
}
hr(token: Tokens.Hr): string {
return '
\n';
}
list(token: Tokens.List): string {
const ordered = token.ordered;
const start = token.start;
let body = '';
for (let j = 0; j < token.items.length; j++) {
const item = token.items[j];
body += this.listitem(item);
}
const type = ordered ? 'ol' : 'ul';
const startAttr = (ordered && start !== 1) ? (' start="' + start + '"') : '';
return '<' + type + startAttr + '>\n' + body + '' + type + '>\n';
}
listitem(item: Tokens.ListItem): string {
let itemBody = '';
if (item.task) {
const checkbox = this.checkbox({ checked: !!item.checked });
if (item.loose) {
if (item.tokens[0]?.type === 'paragraph') {
item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {
item.tokens[0].tokens[0].text = checkbox + ' ' + escape(item.tokens[0].tokens[0].text);
item.tokens[0].tokens[0].escaped = true;
}
} else {
item.tokens.unshift({
type: 'text',
raw: checkbox + ' ',
text: checkbox + ' ',
escaped: true,
});
}
} else {
itemBody += checkbox + ' ';
}
}
itemBody += this.parser.parse(item.tokens, !!item.loose);
return `${itemBody}\n`;
}
checkbox({ checked }: Tokens.Checkbox): string {
return '';
}
paragraph({ tokens }: Tokens.Paragraph): string {
return `${this.parser.parseInline(tokens)}
\n`;
}
table(token: Tokens.Table): string {
let header = '';
// header
let cell = '';
for (let j = 0; j < token.header.length; j++) {
cell += this.tablecell(token.header[j]);
}
header += this.tablerow({ text: cell });
let body = '';
for (let j = 0; j < token.rows.length; j++) {
const row = token.rows[j];
cell = '';
for (let k = 0; k < row.length; k++) {
cell += this.tablecell(row[k]);
}
body += this.tablerow({ text: cell });
}
if (body) body = `${body}`;
return '\n'
+ '\n'
+ header
+ '\n'
+ body
+ '
\n';
}
tablerow({ text }: Tokens.TableRow): string {
return `\n${text}
\n`;
}
tablecell(token: Tokens.TableCell): string {
const content = this.parser.parseInline(token.tokens);
const type = token.header ? 'th' : 'td';
const tag = token.align
? `<${type} align="${token.align}">`
: `<${type}>`;
return tag + content + `${type}>\n`;
}
/**
* span level renderer
*/
strong({ tokens }: Tokens.Strong): string {
return `${this.parser.parseInline(tokens)}`;
}
em({ tokens }: Tokens.Em): string {
return `${this.parser.parseInline(tokens)}`;
}
codespan({ text }: Tokens.Codespan): string {
return `${escape(text, true)}
`;
}
br(token: Tokens.Br): string {
return '
';
}
del({ tokens }: Tokens.Del): string {
return `${this.parser.parseInline(tokens)}`;
}
link({ href, title, tokens }: Tokens.Link): string {
const text = this.parser.parseInline(tokens);
const cleanHref = cleanUrl(href);
if (cleanHref === null) {
return text;
}
href = cleanHref;
let out = '' + text + '';
return out;
}
image({ href, title, text, tokens }: Tokens.Image): string {
if (tokens) {
text = this.parser.parseInline(tokens, this.parser.textRenderer);
}
const cleanHref = cleanUrl(href);
if (cleanHref === null) {
return escape(text);
}
href = cleanHref;
let out = `
';
return out;
}
text(token: Tokens.Text | Tokens.Escape) : string {
return 'tokens' in token && token.tokens
? this.parser.parseInline(token.tokens)
: ('escaped' in token && token.escaped ? token.text : escape(token.text));
}
}