conflutora
Version:
Provider to convert and publish Antora documentation on Confluence
112 lines • 4.89 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.HtmlParserService = void 0;
const node_html_parser_1 = require("node-html-parser");
const xmlbuilder_1 = __importDefault(require("xmlbuilder"));
const Logger_js_1 = require("../utils/Logger.js");
class HtmlParserService {
logger = new Logger_js_1.Logger(this.constructor.name);
tagMapper = {
p: (xml, elem) => xml.ele('p').raw(elem.innerHTML.trim()),
h1: (xml, elem) => xml.ele('h1').raw(elem.innerHTML),
h2: (xml, elem) => xml.ele('h2').raw(elem.innerHTML),
h3: (xml, elem) => xml.ele('h3').raw(elem.innerHTML),
h4: (xml, elem) => xml.ele('h4').raw(elem.innerHTML),
h5: (xml, elem) => xml.ele('h5').raw(elem.innerHTML),
h6: (xml, elem) => xml.ele('h6').raw(elem.innerHTML),
hr: (xml, elem) => xml.ele('hr', { 'ac:layout': 'default' }).up(), // Use 'up()' to go back to the parent after appending the hr tag
ul: (xml, elem) => {
const ul = xml.ele('ul');
elem.childNodes.filter(child => child.rawTagName === 'li').forEach(child => {
this.tagMapper.li(ul, child);
});
},
ol: (xml, elem) => {
const ol = xml.ele('ol');
elem.childNodes.filter(child => child.rawTagName === 'li').forEach(child => {
this.tagMapper.li(ol, child);
});
},
li: (xml, elem) => xml.ele('li').raw(elem.innerHTML),
a: (xml, elem) => {
const href = elem.getAttribute('href') ?? '#';
xml.ele('a', { href }).raw(elem.textContent.trim());
},
img: (xml, elem) => {
const src = elem.getAttribute('src') ?? '';
const alt = elem.getAttribute('alt') ?? '';
xml.ele('ac:image', { 'ri:filename': src })
.ele('ri:attachment', { 'ri:filename': src })
.up()
.ele('ac:plain-text-link-body')
.txt(``);
}
// img: (xml, elem) => {
// const src = elem.getAttribute('src') ?? ''
// const alt = elem.getAttribute('alt') ?? ''
// const img = xml.ele('ac:image', { 'ri:filename': src })
// img.ele('ri:attachment', { 'ri:filename': src }).up()
// img.ele('ac:plain-text-link-body')
// .text(``)
// }
};
getPageTitle(htmlContent) {
const dom = (0, node_html_parser_1.parse)(htmlContent);
const titleSelectors = ['h1.page', 'h1', 'h2'];
for (const selector of titleSelectors) {
const titleElement = dom.querySelector(selector);
if (titleElement?.text) {
return titleElement.text.trim();
}
else {
this.logger.debug(`No title found using selector '${selector}'`);
}
}
this.logger.error('Failed to extract a title from the input');
return undefined;
}
extractBodyContent(htmlContent) {
const dom = (0, node_html_parser_1.parse)(htmlContent, { blockTextElements: { code: true } });
return dom.querySelector('article.doc')?.innerHTML ?? dom.querySelector('main.article')?.innerHTML ?? '';
}
convertToConfluenceXML(htmlContent) {
// this.logger.info('Converting HTML to Confluence XML', htmlContent)
const dom = (0, node_html_parser_1.parse)(htmlContent);
const xml = xmlbuilder_1.default.create('ac:rich-text-body', { version: '1.0', encoding: 'UTF-8', standalone: true, headless: true });
// Convert HTML nodes to Confluence XHTML format
dom.childNodes.forEach(node => {
if (node.nodeType === 1) {
this.htmlToConfluence(xml, node);
}
});
const xmlContent = xml.end({ pretty: true });
// this.logger.info('XML result:', xmlContent)
return xmlContent;
}
htmlToConfluence(xml, elem) {
const tag = elem.tagName.toLowerCase();
const mapper = this.tagMapper[tag];
if (mapper) {
mapper(xml, elem);
}
else if (elem.childNodes.length > 0) { // Generic handling for unknown tags
const generic = xml.ele(tag);
elem.childNodes.forEach(child => {
if (child.nodeType === 1) {
this.htmlToConfluence(generic, child);
}
else {
generic.text(child.rawText);
}
});
}
else {
xml.ele(tag).raw(elem.innerHTML); // Fallback to raw HTML
}
}
}
exports.HtmlParserService = HtmlParserService;
//# sourceMappingURL=html-parser.service.js.map