@aiquants/html-to-markdown 0.1.3 → 0.1.5
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 +102 -19
- package/dist/{core-DUdcm-c8.cjs → core-D2dlEt1l.cjs} +1 -1
- package/dist/{core-0q2nkcWH.js → core-DU_246Q7.js} +202 -29
- package/dist/index.cjs +1 -1
- package/dist/index.js +8 -2
- package/dist/main.cjs +1 -1
- package/dist/main.js +6 -2
- package/dist/mcp-server-CpmnW1p8.js +283 -0
- package/dist/mcp-server-D4Mj1IQ9.cjs +1 -0
- package/dist/mcp-server-streamable-Bu7QAr3W.cjs +1 -0
- package/dist/mcp-server-streamable-CQD5zK30.js +7538 -0
- package/dist/mcp-streamable.cjs +2 -0
- package/dist/mcp-streamable.js +6 -0
- package/dist/mcp.cjs +2 -0
- package/dist/mcp.js +13 -0
- package/dist/src/core.d.ts +8 -5
- package/dist/src/index.d.ts +2 -0
- package/dist/src/mcp-server-streamable.d.ts +74 -0
- package/dist/src/mcp-server.d.ts +57 -0
- package/dist/src/mcp-streamable.d.ts +6 -0
- package/dist/src/mcp.d.ts +6 -0
- package/dist/src/plugins/index.d.ts +2 -0
- package/dist/src/plugins/rehype-named-anchors.d.ts +2 -0
- package/dist/src/plugins/rehype-paragraph-wrapper.d.ts +6 -0
- package/dist/src/types.d.ts +5 -0
- package/dist/src/version.d.ts +9 -0
- package/dist/tests/core-unified.test.d.ts +5 -0
- package/dist/tests/coverage-complete.test.d.ts +5 -0
- package/dist/tests/mcp-unified.test.d.ts +5 -0
- package/dist/tests/plugins-unified.test.d.ts +5 -0
- package/dist/tests/test-client.d.ts +4 -0
- package/dist/version-BRVBmpor.js +11318 -0
- package/dist/version-DTaUKNBS.cjs +1 -0
- package/mcp.json +14 -0
- package/package.json +27 -8
- package/dist/tests/100-percent-final.test.d.ts +0 -1
- package/dist/tests/absolute-final-coverage.test.d.ts +0 -1
- package/dist/tests/browser-100.test.d.ts +0 -1
- package/dist/tests/browser-coverage.test.d.ts +0 -1
- package/dist/tests/browser.test.d.ts +0 -1
- package/dist/tests/cli.test.d.ts +0 -1
- package/dist/tests/converter-coverage.test.d.ts +0 -1
- package/dist/tests/converter.test.d.ts +0 -1
- package/dist/tests/core.test.d.ts +0 -1
- package/dist/tests/coverage-edge-cases.test.d.ts +0 -1
- package/dist/tests/direct-coverage.test.d.ts +0 -1
- package/dist/tests/final-100-percent.test.d.ts +0 -1
- package/dist/tests/final-coverage.test.d.ts +0 -1
- package/dist/tests/i18n.test.d.ts +0 -1
- package/dist/tests/index.test.d.ts +0 -1
- package/dist/tests/line-70-coverage.test.d.ts +0 -1
- package/dist/tests/main.test.d.ts +0 -1
- package/dist/tests/plugins.test.d.ts +0 -1
- package/dist/tests/readme-usage.test.d.ts +0 -1
- package/dist/tests/rehype-absolute-links-coverage.test.d.ts +0 -1
- package/dist/tests/rehype-absolute-links.test.d.ts +0 -1
- package/dist/tests/rehype-sanitize-html-coverage.test.d.ts +0 -1
- package/dist/tests/rehype-sanitize-html.test.d.ts +0 -1
- package/dist/tests/rehype-wikipedia-footnotes.test.d.ts +0 -1
- package/dist/tests/types.test.d.ts +0 -1
- package/dist/tests/ultimate-coverage.test.d.ts +0 -1
- /package/dist/tests/{100-percent-coverage.test.d.ts → entry-points-error.test.d.ts} +0 -0
|
@@ -19494,9 +19494,39 @@ function bail(error) {
|
|
|
19494
19494
|
throw error;
|
|
19495
19495
|
}
|
|
19496
19496
|
}
|
|
19497
|
+
var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
|
|
19497
19498
|
function getDefaultExportFromCjs(x) {
|
|
19498
19499
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
|
|
19499
19500
|
}
|
|
19501
|
+
function getAugmentedNamespace(n) {
|
|
19502
|
+
if (Object.prototype.hasOwnProperty.call(n, "__esModule")) return n;
|
|
19503
|
+
var f = n.default;
|
|
19504
|
+
if (typeof f == "function") {
|
|
19505
|
+
var a2 = function a3() {
|
|
19506
|
+
var isInstance = false;
|
|
19507
|
+
try {
|
|
19508
|
+
isInstance = this instanceof a3;
|
|
19509
|
+
} catch {
|
|
19510
|
+
}
|
|
19511
|
+
if (isInstance) {
|
|
19512
|
+
return Reflect.construct(f, arguments, this.constructor);
|
|
19513
|
+
}
|
|
19514
|
+
return f.apply(this, arguments);
|
|
19515
|
+
};
|
|
19516
|
+
a2.prototype = f.prototype;
|
|
19517
|
+
} else a2 = {};
|
|
19518
|
+
Object.defineProperty(a2, "__esModule", { value: true });
|
|
19519
|
+
Object.keys(n).forEach(function(k) {
|
|
19520
|
+
var d = Object.getOwnPropertyDescriptor(n, k);
|
|
19521
|
+
Object.defineProperty(a2, k, d.get ? d : {
|
|
19522
|
+
enumerable: true,
|
|
19523
|
+
get: function() {
|
|
19524
|
+
return n[k];
|
|
19525
|
+
}
|
|
19526
|
+
});
|
|
19527
|
+
});
|
|
19528
|
+
return a2;
|
|
19529
|
+
}
|
|
19500
19530
|
var extend$1;
|
|
19501
19531
|
var hasRequiredExtend;
|
|
19502
19532
|
function requireExtend() {
|
|
@@ -20384,6 +20414,123 @@ const rehypeAbsoluteLinks = (options) => {
|
|
|
20384
20414
|
});
|
|
20385
20415
|
};
|
|
20386
20416
|
};
|
|
20417
|
+
const blockLevelTags = /* @__PURE__ */ new Set([
|
|
20418
|
+
"address",
|
|
20419
|
+
"article",
|
|
20420
|
+
"aside",
|
|
20421
|
+
"blockquote",
|
|
20422
|
+
"br",
|
|
20423
|
+
"details",
|
|
20424
|
+
"dialog",
|
|
20425
|
+
"dd",
|
|
20426
|
+
"div",
|
|
20427
|
+
"dl",
|
|
20428
|
+
"dt",
|
|
20429
|
+
"fieldset",
|
|
20430
|
+
"figcaption",
|
|
20431
|
+
"figure",
|
|
20432
|
+
"footer",
|
|
20433
|
+
"form",
|
|
20434
|
+
// "h1", // # 見出し<span id="custom-id"></span> となってしまうのを回避
|
|
20435
|
+
// "h2", // ## 見出し<span id="custom-id"></span> となってしまうのを回避
|
|
20436
|
+
// "h3", // ### 見出し<span id="custom-id"></span> となってしまうのを回避
|
|
20437
|
+
// "h4", // #### 見出し<span id="custom-id"></span> となってしまうのを回避
|
|
20438
|
+
// "h5", // ##### 見出し<span id="custom-id"></span> となってしまうのを回避
|
|
20439
|
+
// "h6", // ###### 見出し<span id="custom-id"></span> となってしまうのを回避
|
|
20440
|
+
"header",
|
|
20441
|
+
"hgroup",
|
|
20442
|
+
"hr",
|
|
20443
|
+
"li",
|
|
20444
|
+
"main",
|
|
20445
|
+
"nav",
|
|
20446
|
+
"ol",
|
|
20447
|
+
"p",
|
|
20448
|
+
"pre",
|
|
20449
|
+
"section",
|
|
20450
|
+
"table",
|
|
20451
|
+
"ul"
|
|
20452
|
+
]);
|
|
20453
|
+
function hasBlockElement(node2) {
|
|
20454
|
+
let found = false;
|
|
20455
|
+
visit(node2, "element", (el) => {
|
|
20456
|
+
if (blockLevelTags.has(el.tagName)) {
|
|
20457
|
+
found = true;
|
|
20458
|
+
return EXIT;
|
|
20459
|
+
}
|
|
20460
|
+
});
|
|
20461
|
+
return found;
|
|
20462
|
+
}
|
|
20463
|
+
const slugger = new BananaSlug();
|
|
20464
|
+
const rehypeNamedAnchors = () => (tree) => {
|
|
20465
|
+
visit(tree, "element", (node2, index2, parent) => {
|
|
20466
|
+
if (parent && typeof index2 === "number" && node2.properties && node2.properties.id) {
|
|
20467
|
+
const id = String(node2.properties.id);
|
|
20468
|
+
if (id && ["h1", "h2", "h3", "h4", "h5", "h6"].includes(node2.tagName)) {
|
|
20469
|
+
const customId = slugger.slug(id);
|
|
20470
|
+
node2.children.push({
|
|
20471
|
+
type: "text",
|
|
20472
|
+
value: ` {#${customId}}`
|
|
20473
|
+
});
|
|
20474
|
+
return;
|
|
20475
|
+
}
|
|
20476
|
+
if (node2.tagName === "span" && id && Object.keys(node2.properties || {}).length === 1) {
|
|
20477
|
+
return;
|
|
20478
|
+
}
|
|
20479
|
+
const anchorNode = {
|
|
20480
|
+
type: "element",
|
|
20481
|
+
tagName: "span",
|
|
20482
|
+
properties: { id },
|
|
20483
|
+
children: []
|
|
20484
|
+
};
|
|
20485
|
+
if (hasBlockElement(node2)) {
|
|
20486
|
+
let firstInlineInfo = null;
|
|
20487
|
+
visit(node2, (child, childIndex, childParent) => {
|
|
20488
|
+
if (childParent && typeof childIndex === "number") {
|
|
20489
|
+
if (child.type === "element" && !blockLevelTags.has(child.tagName) || child.type === "text" && child.value.trim() !== "") {
|
|
20490
|
+
firstInlineInfo = {
|
|
20491
|
+
node: node2,
|
|
20492
|
+
parent: childParent,
|
|
20493
|
+
index: childIndex
|
|
20494
|
+
};
|
|
20495
|
+
return EXIT;
|
|
20496
|
+
}
|
|
20497
|
+
}
|
|
20498
|
+
});
|
|
20499
|
+
if (firstInlineInfo) {
|
|
20500
|
+
const inline = firstInlineInfo;
|
|
20501
|
+
inline.parent.children.splice(inline.index + 1, 0, anchorNode);
|
|
20502
|
+
delete node2.properties.id;
|
|
20503
|
+
}
|
|
20504
|
+
return;
|
|
20505
|
+
} else {
|
|
20506
|
+
parent.children.splice(index2 + 1, 0, anchorNode);
|
|
20507
|
+
delete node2.properties.id;
|
|
20508
|
+
return index2 + 1;
|
|
20509
|
+
}
|
|
20510
|
+
}
|
|
20511
|
+
});
|
|
20512
|
+
};
|
|
20513
|
+
const rehypeParagraphWrapper = () => (tree) => {
|
|
20514
|
+
visit(tree, "element", (node2, index2, parent) => {
|
|
20515
|
+
if (parent && typeof index2 === "number") {
|
|
20516
|
+
const nextNode = parent.children[index2 + 1];
|
|
20517
|
+
if (nextNode && nextNode.type === "element" && nextNode.tagName === "span" && nextNode.properties?.id && Object.keys(nextNode.properties).length === 1) {
|
|
20518
|
+
const parentIsBlock = !parent || parent.type === "root" || ["body", "div", "section", "article", "aside", "footer", "header", "nav", "td", "th", "li"].includes(parent.tagName);
|
|
20519
|
+
if (parentIsBlock) {
|
|
20520
|
+
const paragraph2 = {
|
|
20521
|
+
type: "element",
|
|
20522
|
+
tagName: "p",
|
|
20523
|
+
properties: {},
|
|
20524
|
+
children: [node2, nextNode]
|
|
20525
|
+
// 現在のノードと次の span ノードを子として含める
|
|
20526
|
+
};
|
|
20527
|
+
parent.children.splice(index2, 2, paragraph2);
|
|
20528
|
+
return index2 + 1;
|
|
20529
|
+
}
|
|
20530
|
+
}
|
|
20531
|
+
}
|
|
20532
|
+
});
|
|
20533
|
+
};
|
|
20387
20534
|
const rehypeSanitizeHtml = () => {
|
|
20388
20535
|
return (tree) => {
|
|
20389
20536
|
visit(tree, (node2, index2, parent) => {
|
|
@@ -20477,7 +20624,7 @@ const rehypeWikipediaFootnotes = () => {
|
|
|
20477
20624
|
};
|
|
20478
20625
|
};
|
|
20479
20626
|
const handleTableCell = (_state, node2, _parent) => {
|
|
20480
|
-
const allowedTags = ["br", "hr", "h1", "h2", "h3", "h4", "h5", "h6", "strong", "em", "b", "i", "u", "s", "strike", "del", "ins", "code", "ul", "ol", "li", "a", "img", "blockquote", "pre", "table", "thead", "tbody", "tfoot", "tr", "th", "td"];
|
|
20627
|
+
const allowedTags = ["br", "hr", "h1", "h2", "h3", "h4", "h5", "h6", "strong", "em", "b", "i", "u", "s", "strike", "del", "ins", "code", "ul", "ol", "li", "a", "img", "blockquote", "pre", "table", "thead", "tbody", "tfoot", "tr", "th", "td", "style"];
|
|
20481
20628
|
const allowedAttributes = ["style", "class", "id", "colspan", "rowspan", "width", "height", "align", "href", "src", "title", "alt"];
|
|
20482
20629
|
visit(node2, "element", (elementNode, index2, parent) => {
|
|
20483
20630
|
if (!parent || typeof index2 !== "number") {
|
|
@@ -20535,22 +20682,33 @@ const handleTableCell = (_state, node2, _parent) => {
|
|
|
20535
20682
|
};
|
|
20536
20683
|
const convertHtmlToMarkdown = async (html2, baseUrl, locale) => {
|
|
20537
20684
|
console.log(getMessage(locale, "convert_start"));
|
|
20538
|
-
const
|
|
20539
|
-
const file = await unified().use(rehypeParse, { fragment: true }).use(rehypeRaw).use(rehypeSanitizeHtml).use(rehypeSlug).use(rehypeAbsoluteLinks, { baseUrl }).use(
|
|
20685
|
+
const slugger2 = new BananaSlug();
|
|
20686
|
+
const file = await unified().use(rehypeParse, { fragment: true }).use(rehypeRaw).use(rehypeSanitizeHtml).use(rehypeWikipediaFootnotes).use(rehypeNamedAnchors).use(rehypeSlug).use(rehypeParagraphWrapper).use(rehypeAbsoluteLinks, { baseUrl }).use(rehypeRemark, {
|
|
20540
20687
|
handlers: {
|
|
20688
|
+
span(state, node2) {
|
|
20689
|
+
const id = node2.properties?.id;
|
|
20690
|
+
if (id && Object.keys(node2.properties || {}).length === 1) {
|
|
20691
|
+
const children = state.all(node2);
|
|
20692
|
+
if (children.length === 0) {
|
|
20693
|
+
return { type: "html", value: `<span id="${String(id)}"></span>` };
|
|
20694
|
+
}
|
|
20695
|
+
return [{ type: "html", value: `<span id="${String(id)}">` }, ...children, { type: "html", value: "</span>" }];
|
|
20696
|
+
}
|
|
20697
|
+
return state.all(node2);
|
|
20698
|
+
},
|
|
20541
20699
|
a(state, node2) {
|
|
20542
20700
|
const hasComplexChildren = node2.children.some((child) => child.type === "element" && ["dl", "ul", "ol", "table", "div"].includes(child.tagName));
|
|
20543
20701
|
if (hasComplexChildren && node2.properties?.href) {
|
|
20544
20702
|
const linkText2 = String(node2.properties.ariaLabel || "");
|
|
20545
20703
|
if (linkText2) {
|
|
20546
|
-
const
|
|
20547
|
-
const
|
|
20704
|
+
const url = String(node2.properties.href);
|
|
20705
|
+
const linkNode2 = {
|
|
20548
20706
|
type: "link",
|
|
20549
|
-
url
|
|
20707
|
+
url,
|
|
20550
20708
|
children: [{ type: "text", value: linkText2 }]
|
|
20551
20709
|
};
|
|
20552
20710
|
const otherContent = state.all(node2);
|
|
20553
|
-
return [
|
|
20711
|
+
return [linkNode2, { type: "text", value: "\n" }, ...otherContent];
|
|
20554
20712
|
}
|
|
20555
20713
|
}
|
|
20556
20714
|
const extractTextFromHast = (n) => {
|
|
@@ -20584,24 +20742,27 @@ const convertHtmlToMarkdown = async (html2, baseUrl, locale) => {
|
|
|
20584
20742
|
return false;
|
|
20585
20743
|
});
|
|
20586
20744
|
};
|
|
20745
|
+
let linkNode;
|
|
20587
20746
|
if (containsImage(node2)) {
|
|
20588
|
-
|
|
20747
|
+
linkNode = {
|
|
20589
20748
|
type: "link",
|
|
20590
20749
|
url: String(node2.properties?.href || ""),
|
|
20591
20750
|
title: node2.properties?.title ? String(node2.properties.title) : null,
|
|
20592
20751
|
children: state.all(node2)
|
|
20593
20752
|
};
|
|
20753
|
+
} else {
|
|
20754
|
+
let url = String(node2.properties?.href || "");
|
|
20755
|
+
if (url.startsWith("#")) {
|
|
20756
|
+
url = `#${slugger2.slug(url.substring(1))}`;
|
|
20757
|
+
}
|
|
20758
|
+
linkNode = {
|
|
20759
|
+
type: "link",
|
|
20760
|
+
url,
|
|
20761
|
+
title: node2.properties?.title ? String(node2.properties.title) : null,
|
|
20762
|
+
children: [{ type: "text", value: linkText }]
|
|
20763
|
+
};
|
|
20594
20764
|
}
|
|
20595
|
-
|
|
20596
|
-
if (url.startsWith("#")) {
|
|
20597
|
-
url = `#${slugger.slug(url.substring(1))}`;
|
|
20598
|
-
}
|
|
20599
|
-
return {
|
|
20600
|
-
type: "link",
|
|
20601
|
-
url,
|
|
20602
|
-
title: node2.properties?.title ? String(node2.properties.title) : null,
|
|
20603
|
-
children: [{ type: "text", value: linkText }]
|
|
20604
|
-
};
|
|
20765
|
+
return linkNode;
|
|
20605
20766
|
},
|
|
20606
20767
|
td(state, node2, parent) {
|
|
20607
20768
|
return handleTableCell(state, node2);
|
|
@@ -20625,23 +20786,35 @@ const convertHtmlToMarkdown = async (html2, baseUrl, locale) => {
|
|
|
20625
20786
|
console.log(getMessage(locale, "convert_success"));
|
|
20626
20787
|
return correctedMarkdown;
|
|
20627
20788
|
};
|
|
20628
|
-
const htmlToMarkdown = async (
|
|
20629
|
-
const { locale = "en-US" } = options;
|
|
20789
|
+
const htmlToMarkdown = async (urlOrHtml, options = {}) => {
|
|
20790
|
+
const { locale = "en-US", htmlContent } = options;
|
|
20630
20791
|
try {
|
|
20631
|
-
|
|
20632
|
-
|
|
20633
|
-
if (
|
|
20634
|
-
|
|
20635
|
-
|
|
20792
|
+
let htmlContentToProcess;
|
|
20793
|
+
let sourceUrl;
|
|
20794
|
+
if (htmlContent) {
|
|
20795
|
+
htmlContentToProcess = htmlContent;
|
|
20796
|
+
sourceUrl = urlOrHtml || "direct-html-input";
|
|
20797
|
+
} else {
|
|
20798
|
+
new URL(urlOrHtml);
|
|
20799
|
+
htmlContentToProcess = await getHtmlWithPlaywright(urlOrHtml, locale);
|
|
20800
|
+
sourceUrl = urlOrHtml;
|
|
20636
20801
|
}
|
|
20637
|
-
|
|
20638
|
-
|
|
20802
|
+
if (!htmlContentToProcess) {
|
|
20803
|
+
console.error(`No HTML content found for source: ${sourceUrl}`);
|
|
20804
|
+
return { html: "", markdown: "" };
|
|
20805
|
+
}
|
|
20806
|
+
const markdown = await convertHtmlToMarkdown(htmlContentToProcess, sourceUrl, locale);
|
|
20807
|
+
return { html: htmlContentToProcess, markdown };
|
|
20639
20808
|
} catch (error) {
|
|
20640
|
-
|
|
20641
|
-
|
|
20809
|
+
const source = htmlContent ? "HTML string" : `URL: ${urlOrHtml}`;
|
|
20810
|
+
console.error(`An error occurred during the conversion process for ${source}`, error);
|
|
20811
|
+
return { html: "", markdown: "" };
|
|
20642
20812
|
}
|
|
20643
20813
|
};
|
|
20644
20814
|
export {
|
|
20815
|
+
getAugmentedNamespace as a,
|
|
20816
|
+
getDefaultExportFromCjs as b,
|
|
20817
|
+
commonjsGlobal as c,
|
|
20645
20818
|
getMessage as g,
|
|
20646
20819
|
htmlToMarkdown as h
|
|
20647
20820
|
};
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=new(require("happy-dom").Window);Object.assign(global,{document:e.document,window:e,self:e}),Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
const e=new(require("happy-dom").Window);Object.assign(global,{document:e.document,window:e,self:e}),Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("./core-D2dlEt1l.cjs"),t=require("./mcp-server-D4Mj1IQ9.cjs"),c=require("./mcp-server-streamable-Bu7QAr3W.cjs");exports.getMessage=r.getMessage,exports.htmlToMarkdown=r.htmlToMarkdown,exports.createMcpServer=t.createMcpServer,exports.runMcpServer=t.runMcpServer,exports.createStreamableMcpServer=c.createStreamableMcpServer,exports.runStreamableMcpServer=c.runStreamableMcpServer;
|
package/dist/index.js
CHANGED
|
@@ -5,8 +5,14 @@ Object.assign(global, {
|
|
|
5
5
|
window,
|
|
6
6
|
self: window
|
|
7
7
|
});
|
|
8
|
-
import { g, h } from "./core-
|
|
8
|
+
import { g, h } from "./core-DU_246Q7.js";
|
|
9
|
+
import { c, r } from "./mcp-server-CpmnW1p8.js";
|
|
10
|
+
import { c as c2, r as r2 } from "./mcp-server-streamable-CQD5zK30.js";
|
|
9
11
|
export {
|
|
12
|
+
c as createMcpServer,
|
|
13
|
+
c2 as createStreamableMcpServer,
|
|
10
14
|
g as getMessage,
|
|
11
|
-
h as htmlToMarkdown
|
|
15
|
+
h as htmlToMarkdown,
|
|
16
|
+
r as runMcpServer,
|
|
17
|
+
r2 as runStreamableMcpServer
|
|
12
18
|
};
|
package/dist/main.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
Object.create,Object.defineProperty,Object.getOwnPropertyDescriptor,Object.getOwnPropertyNames,Object.getPrototypeOf,Object.prototype.hasOwnProperty;const e=new(require("happy-dom").Window);Object.assign(global,{document:e.document,window:e,self:e});const t=require("./core-
|
|
2
|
+
Object.create,Object.defineProperty,Object.getOwnPropertyDescriptor,Object.getOwnPropertyNames,Object.getPrototypeOf,Object.prototype.hasOwnProperty;const e=new(require("happy-dom").Window);Object.assign(global,{document:e.document,window:e,self:e});const t=require("./core-D2dlEt1l.cjs");var r="undefined"!=typeof document?document.currentScript:null;(async()=>{(("undefined"==typeof document?require("url").pathToFileURL(__filename).href:r&&"SCRIPT"===r.tagName.toUpperCase()&&r.src||new URL("main.cjs",document.baseURI).href).endsWith(process.argv[1])||process.argv[1]&&process.argv[1].includes("vite-node"))&&(async()=>{const e=(await import("yargs-parser")).default,r=await import("node:fs"),o=await import("node:path"),c=e(process.argv.slice(2),{string:["locale","output"],alias:{output:["o"]},default:{locale:"en-US"}}),s=c._[0],n=c.locale,a=c.output;s||process.exit(1);try{new URL(s)}catch(i){process.exit(1)}try{const{markdown:e,html:c}=await t.htmlToMarkdown(s,{locale:n});let i;if(a){i=o.resolve(process.cwd(),a);const e=o.dirname(i);r.existsSync(e)||r.mkdirSync(e,{recursive:!0})}else{const e=`${s.replace(/https?:\/\//,"").replace(/[^a-zA-Z0-9]/g,"_")}_${Date.now()}.md`,t=o.join(process.cwd(),".outputs","raw");r.existsSync(t)||r.mkdirSync(t,{recursive:!0}),i=o.join(t,e)}r.writeFileSync(i,e);const p=o.parse(i),l=o.join(p.dir,`${p.name}.html`);r.writeFileSync(l,c)}catch(i){process.exit(1)}})()})();
|
package/dist/main.js
CHANGED
|
@@ -6,7 +6,7 @@ Object.assign(global, {
|
|
|
6
6
|
window,
|
|
7
7
|
self: window
|
|
8
8
|
});
|
|
9
|
-
import { g as getMessage, h as htmlToMarkdown } from "./core-
|
|
9
|
+
import { g as getMessage, h as htmlToMarkdown } from "./core-DU_246Q7.js";
|
|
10
10
|
const runCli = async () => {
|
|
11
11
|
const yargsParser = (await import("yargs-parser")).default;
|
|
12
12
|
const fs = await import("node:fs");
|
|
@@ -44,7 +44,7 @@ ${getMessage(locale, "cli_start")}`);
|
|
|
44
44
|
if (outputFile) {
|
|
45
45
|
console.info(getMessage(locale, "cli_output", { path: outputFile }));
|
|
46
46
|
}
|
|
47
|
-
const markdown = await htmlToMarkdown(targetUrl, { locale });
|
|
47
|
+
const { markdown, html } = await htmlToMarkdown(targetUrl, { locale });
|
|
48
48
|
let filePath;
|
|
49
49
|
if (outputFile) {
|
|
50
50
|
filePath = path.resolve(process.cwd(), outputFile);
|
|
@@ -63,9 +63,13 @@ ${getMessage(locale, "cli_start")}`);
|
|
|
63
63
|
filePath = path.join(outputDir, fileName);
|
|
64
64
|
}
|
|
65
65
|
fs.writeFileSync(filePath, markdown);
|
|
66
|
+
const parsedPath = path.parse(filePath);
|
|
67
|
+
const htmlFilePath = path.join(parsedPath.dir, `${parsedPath.name}.html`);
|
|
68
|
+
fs.writeFileSync(htmlFilePath, html);
|
|
66
69
|
console.info(`
|
|
67
70
|
${getMessage(locale, "success_save")}`);
|
|
68
71
|
console.info(getMessage(locale, "success_path", { path: filePath }));
|
|
72
|
+
console.info(getMessage(locale, "success_path", { path: htmlFilePath }));
|
|
69
73
|
} catch (error) {
|
|
70
74
|
console.error(`
|
|
71
75
|
${getMessage(locale, "error_app")}`, error);
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { Window } from "happy-dom";
|
|
2
|
+
const window = new Window();
|
|
3
|
+
Object.assign(global, {
|
|
4
|
+
document: window.document,
|
|
5
|
+
window,
|
|
6
|
+
self: window
|
|
7
|
+
});
|
|
8
|
+
import { J as JSONRPCMessageSchema, g as getPackageVersion, S as Server, L as ListToolsRequestSchema, C as CallToolRequestSchema } from "./version-BRVBmpor.js";
|
|
9
|
+
import process from "node:process";
|
|
10
|
+
import { h as htmlToMarkdown } from "./core-DU_246Q7.js";
|
|
11
|
+
class ReadBuffer {
|
|
12
|
+
append(chunk) {
|
|
13
|
+
this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk;
|
|
14
|
+
}
|
|
15
|
+
readMessage() {
|
|
16
|
+
if (!this._buffer) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const index = this._buffer.indexOf("\n");
|
|
20
|
+
if (index === -1) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
const line = this._buffer.toString("utf8", 0, index).replace(/\r$/, "");
|
|
24
|
+
this._buffer = this._buffer.subarray(index + 1);
|
|
25
|
+
return deserializeMessage(line);
|
|
26
|
+
}
|
|
27
|
+
clear() {
|
|
28
|
+
this._buffer = void 0;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function deserializeMessage(line) {
|
|
32
|
+
return JSONRPCMessageSchema.parse(JSON.parse(line));
|
|
33
|
+
}
|
|
34
|
+
function serializeMessage(message) {
|
|
35
|
+
return JSON.stringify(message) + "\n";
|
|
36
|
+
}
|
|
37
|
+
class StdioServerTransport {
|
|
38
|
+
constructor(_stdin = process.stdin, _stdout = process.stdout) {
|
|
39
|
+
this._stdin = _stdin;
|
|
40
|
+
this._stdout = _stdout;
|
|
41
|
+
this._readBuffer = new ReadBuffer();
|
|
42
|
+
this._started = false;
|
|
43
|
+
this._ondata = (chunk) => {
|
|
44
|
+
this._readBuffer.append(chunk);
|
|
45
|
+
this.processReadBuffer();
|
|
46
|
+
};
|
|
47
|
+
this._onerror = (error) => {
|
|
48
|
+
var _a;
|
|
49
|
+
(_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Starts listening for messages on stdin.
|
|
54
|
+
*/
|
|
55
|
+
async start() {
|
|
56
|
+
if (this._started) {
|
|
57
|
+
throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");
|
|
58
|
+
}
|
|
59
|
+
this._started = true;
|
|
60
|
+
this._stdin.on("data", this._ondata);
|
|
61
|
+
this._stdin.on("error", this._onerror);
|
|
62
|
+
}
|
|
63
|
+
processReadBuffer() {
|
|
64
|
+
var _a, _b;
|
|
65
|
+
while (true) {
|
|
66
|
+
try {
|
|
67
|
+
const message = this._readBuffer.readMessage();
|
|
68
|
+
if (message === null) {
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
(_a = this.onmessage) === null || _a === void 0 ? void 0 : _a.call(this, message);
|
|
72
|
+
} catch (error) {
|
|
73
|
+
(_b = this.onerror) === null || _b === void 0 ? void 0 : _b.call(this, error);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async close() {
|
|
78
|
+
var _a;
|
|
79
|
+
this._stdin.off("data", this._ondata);
|
|
80
|
+
this._stdin.off("error", this._onerror);
|
|
81
|
+
const remainingDataListeners = this._stdin.listenerCount("data");
|
|
82
|
+
if (remainingDataListeners === 0) {
|
|
83
|
+
this._stdin.pause();
|
|
84
|
+
}
|
|
85
|
+
this._readBuffer.clear();
|
|
86
|
+
(_a = this.onclose) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
87
|
+
}
|
|
88
|
+
send(message) {
|
|
89
|
+
return new Promise((resolve) => {
|
|
90
|
+
const json = serializeMessage(message);
|
|
91
|
+
if (this._stdout.write(json)) {
|
|
92
|
+
resolve();
|
|
93
|
+
} else {
|
|
94
|
+
this._stdout.once("drain", resolve);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function parseHtmlToMarkdownArgs(args) {
|
|
100
|
+
if (!args || typeof args !== "object") {
|
|
101
|
+
throw new Error("Arguments are required");
|
|
102
|
+
}
|
|
103
|
+
const { url, html_content, locale = "en-US", output_format = "markdown" } = args;
|
|
104
|
+
if (!url && !html_content) {
|
|
105
|
+
throw new Error("Either 'url' or 'html_content' is required");
|
|
106
|
+
}
|
|
107
|
+
if (url && typeof url !== "string") {
|
|
108
|
+
throw new Error("'url' must be a string");
|
|
109
|
+
}
|
|
110
|
+
if (html_content && typeof html_content !== "string") {
|
|
111
|
+
throw new Error("'html_content' must be a string");
|
|
112
|
+
}
|
|
113
|
+
if (locale && !["en-US", "ja-JP"].includes(locale)) {
|
|
114
|
+
throw new Error("'locale' must be 'en-US' or 'ja-JP'");
|
|
115
|
+
}
|
|
116
|
+
if (output_format && !["markdown", "html", "both"].includes(output_format)) {
|
|
117
|
+
throw new Error("'output_format' must be 'markdown', 'html', or 'both'");
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
url,
|
|
121
|
+
html_content,
|
|
122
|
+
locale,
|
|
123
|
+
output_format
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
class HtmlToMarkdownMcpServer {
|
|
127
|
+
constructor() {
|
|
128
|
+
this.version = getPackageVersion();
|
|
129
|
+
this.server = new Server(
|
|
130
|
+
{
|
|
131
|
+
name: "@aiquants/html-to-markdown",
|
|
132
|
+
version: this.version,
|
|
133
|
+
description: "A tool to dynamically fetch a web page from a given URL and convert it to Markdown."
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
capabilities: {
|
|
137
|
+
tools: {}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
this.setupToolHandlers();
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Setup tool handlers for the MCP server.
|
|
145
|
+
* MCP サーバーのツールハンドラーを設定
|
|
146
|
+
*/
|
|
147
|
+
setupToolHandlers() {
|
|
148
|
+
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
149
|
+
return {
|
|
150
|
+
tools: [
|
|
151
|
+
{
|
|
152
|
+
name: "html_to_markdown",
|
|
153
|
+
description: "Convert HTML content from a URL or HTML string to Markdown format. Supports dynamic content loading and preserves table structures.",
|
|
154
|
+
inputSchema: {
|
|
155
|
+
type: "object",
|
|
156
|
+
properties: {
|
|
157
|
+
url: {
|
|
158
|
+
type: "string",
|
|
159
|
+
description: "The URL of the web page to convert to Markdown"
|
|
160
|
+
},
|
|
161
|
+
html_content: {
|
|
162
|
+
type: "string",
|
|
163
|
+
description: "HTML content as a string to convert to Markdown (alternative to URL)"
|
|
164
|
+
},
|
|
165
|
+
locale: {
|
|
166
|
+
type: "string",
|
|
167
|
+
description: "The locale to use for browser context (en-US or ja-JP)",
|
|
168
|
+
enum: ["en-US", "ja-JP"],
|
|
169
|
+
default: "en-US"
|
|
170
|
+
},
|
|
171
|
+
output_format: {
|
|
172
|
+
type: "string",
|
|
173
|
+
description: "Output format: 'markdown' (default), 'html', or 'both'",
|
|
174
|
+
enum: ["markdown", "html", "both"],
|
|
175
|
+
default: "markdown"
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
anyOf: [{ required: ["url"] }, { required: ["html_content"] }]
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
]
|
|
182
|
+
};
|
|
183
|
+
});
|
|
184
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
185
|
+
switch (request.params.name) {
|
|
186
|
+
case "html_to_markdown": {
|
|
187
|
+
return await this.handleHtmlToMarkdown(request.params.arguments);
|
|
188
|
+
}
|
|
189
|
+
default:
|
|
190
|
+
throw new Error(`Unknown tool: ${request.params.name}`);
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Handle HTML to Markdown conversion tool call.
|
|
196
|
+
* HTML から Markdown への変換ツール呼び出しを処理
|
|
197
|
+
*/
|
|
198
|
+
async handleHtmlToMarkdown(args) {
|
|
199
|
+
try {
|
|
200
|
+
const validatedArgs = parseHtmlToMarkdownArgs(args);
|
|
201
|
+
const { url, html_content, locale = "en-US", output_format = "markdown" } = validatedArgs;
|
|
202
|
+
if (url) {
|
|
203
|
+
try {
|
|
204
|
+
new URL(url);
|
|
205
|
+
} catch {
|
|
206
|
+
throw new Error(`Invalid URL: ${url}`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
const result = await htmlToMarkdown(url || "direct-html-input", {
|
|
210
|
+
locale,
|
|
211
|
+
htmlContent: html_content
|
|
212
|
+
});
|
|
213
|
+
let content;
|
|
214
|
+
switch (output_format) {
|
|
215
|
+
case "markdown":
|
|
216
|
+
content = [
|
|
217
|
+
{
|
|
218
|
+
type: "text",
|
|
219
|
+
text: result.markdown
|
|
220
|
+
}
|
|
221
|
+
];
|
|
222
|
+
break;
|
|
223
|
+
case "html":
|
|
224
|
+
content = [
|
|
225
|
+
{
|
|
226
|
+
type: "text",
|
|
227
|
+
text: result.html
|
|
228
|
+
}
|
|
229
|
+
];
|
|
230
|
+
break;
|
|
231
|
+
case "both":
|
|
232
|
+
content = [
|
|
233
|
+
{
|
|
234
|
+
type: "text",
|
|
235
|
+
text: result.markdown
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
type: "text",
|
|
239
|
+
text: result.html
|
|
240
|
+
}
|
|
241
|
+
];
|
|
242
|
+
break;
|
|
243
|
+
default:
|
|
244
|
+
throw new Error(`Invalid output format: ${output_format}`);
|
|
245
|
+
}
|
|
246
|
+
return {
|
|
247
|
+
content,
|
|
248
|
+
isError: false
|
|
249
|
+
};
|
|
250
|
+
} catch (error) {
|
|
251
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
252
|
+
return {
|
|
253
|
+
content: [
|
|
254
|
+
{
|
|
255
|
+
type: "text",
|
|
256
|
+
text: `Error: ${errorMessage}`
|
|
257
|
+
}
|
|
258
|
+
],
|
|
259
|
+
isError: true
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Start the MCP server.
|
|
265
|
+
* MCP サーバーを開始
|
|
266
|
+
*/
|
|
267
|
+
async start() {
|
|
268
|
+
const transport = new StdioServerTransport();
|
|
269
|
+
await this.server.connect(transport);
|
|
270
|
+
console.error("HTML to Markdown MCP server started");
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
const createMcpServer = () => {
|
|
274
|
+
return new HtmlToMarkdownMcpServer();
|
|
275
|
+
};
|
|
276
|
+
const runMcpServer = async () => {
|
|
277
|
+
const server = createMcpServer();
|
|
278
|
+
await server.start();
|
|
279
|
+
};
|
|
280
|
+
export {
|
|
281
|
+
createMcpServer as c,
|
|
282
|
+
runMcpServer as r
|
|
283
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const t=new(require("happy-dom").Window);Object.assign(global,{document:t.document,window:t,self:t});const r=require("./version-DTaUKNBS.cjs"),e=require("node:process"),o=require("./core-D2dlEt1l.cjs");class n{append(t){this._buffer=this._buffer?Buffer.concat([this._buffer,t]):t}readMessage(){if(!this._buffer)return null;const t=this._buffer.indexOf("\n");if(-1===t)return null;const e=this._buffer.toString("utf8",0,t).replace(/\r$/,"");return this._buffer=this._buffer.subarray(t+1),function(t){return r.JSONRPCMessageSchema.parse(JSON.parse(t))}(e)}clear(){this._buffer=void 0}}class s{constructor(t=e.stdin,r=e.stdout){this._stdin=t,this._stdout=r,this._readBuffer=new n,this._started=!1,this._ondata=t=>{this._readBuffer.append(t),this.processReadBuffer()},this._onerror=t=>{var r;null===(r=this.onerror)||void 0===r||r.call(this,t)}}async start(){if(this._started)throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");this._started=!0,this._stdin.on("data",this._ondata),this._stdin.on("error",this._onerror)}processReadBuffer(){for(var t,r;;)try{const r=this._readBuffer.readMessage();if(null===r)break;null===(t=this.onmessage)||void 0===t||t.call(this,r)}catch(e){null===(r=this.onerror)||void 0===r||r.call(this,e)}}async close(){var t;this._stdin.off("data",this._ondata),this._stdin.off("error",this._onerror);0===this._stdin.listenerCount("data")&&this._stdin.pause(),this._readBuffer.clear(),null===(t=this.onclose)||void 0===t||t.call(this)}send(t){return new Promise(r=>{const e=function(t){return JSON.stringify(t)+"\n"}(t);this._stdout.write(e)?r():this._stdout.once("drain",r)})}}class a{constructor(){this.version=r.getPackageVersion(),this.server=new r.Server({name:"@aiquants/html-to-markdown",version:this.version,description:"A tool to dynamically fetch a web page from a given URL and convert it to Markdown."},{capabilities:{tools:{}}}),this.setupToolHandlers()}setupToolHandlers(){this.server.setRequestHandler(r.ListToolsRequestSchema,async()=>({tools:[{name:"html_to_markdown",description:"Convert HTML content from a URL or HTML string to Markdown format. Supports dynamic content loading and preserves table structures.",inputSchema:{type:"object",properties:{url:{type:"string",description:"The URL of the web page to convert to Markdown"},html_content:{type:"string",description:"HTML content as a string to convert to Markdown (alternative to URL)"},locale:{type:"string",description:"The locale to use for browser context (en-US or ja-JP)",enum:["en-US","ja-JP"],default:"en-US"},output_format:{type:"string",description:"Output format: 'markdown' (default), 'html', or 'both'",enum:["markdown","html","both"],default:"markdown"}},anyOf:[{required:["url"]},{required:["html_content"]}]}}]})),this.server.setRequestHandler(r.CallToolRequestSchema,async t=>{if("html_to_markdown"===t.params.name)return await this.handleHtmlToMarkdown(t.params.arguments);throw new Error(`Unknown tool: ${t.params.name}`)})}async handleHtmlToMarkdown(t){try{const r=function(t){if(!t||"object"!=typeof t)throw new Error("Arguments are required");const{url:r,html_content:e,locale:o="en-US",output_format:n="markdown"}=t;if(!r&&!e)throw new Error("Either 'url' or 'html_content' is required");if(r&&"string"!=typeof r)throw new Error("'url' must be a string");if(e&&"string"!=typeof e)throw new Error("'html_content' must be a string");if(o&&!["en-US","ja-JP"].includes(o))throw new Error("'locale' must be 'en-US' or 'ja-JP'");if(n&&!["markdown","html","both"].includes(n))throw new Error("'output_format' must be 'markdown', 'html', or 'both'");return{url:r,html_content:e,locale:o,output_format:n}}(t),{url:e,html_content:n,locale:s="en-US",output_format:a="markdown"}=r;if(e)try{new URL(e)}catch{throw new Error(`Invalid URL: ${e}`)}const i=await o.htmlToMarkdown(e||"direct-html-input",{locale:s,htmlContent:n});let c;switch(a){case"markdown":c=[{type:"text",text:i.markdown}];break;case"html":c=[{type:"text",text:i.html}];break;case"both":c=[{type:"text",text:i.markdown},{type:"text",text:i.html}];break;default:throw new Error(`Invalid output format: ${a}`)}return{content:c,isError:!1}}catch(r){return{content:[{type:"text",text:`Error: ${r instanceof Error?r.message:String(r)}`}],isError:!0}}}async start(){const t=new s;await this.server.connect(t)}}const i=()=>new a;exports.createMcpServer=i,exports.runMcpServer=async()=>{const t=i();await t.start()};
|