webforai 1.4.0 → 1.5.0
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/LICENSE +1 -1
- package/README.md +61 -3
- package/dist/bin.js +233 -0
- package/dist/cjs/bin.js +254 -0
- package/dist/cjs/extract-hast/readability.js +13 -12
- package/dist/cjs/html-to-markdown.test.js +3 -3
- package/dist/cjs/index.js +5 -0
- package/dist/cjs/utils/bin-utils.js +124 -0
- package/dist/extract-hast/readability.js +13 -12
- package/dist/html-to-markdown.test.js +3 -3
- package/dist/index.js +3 -0
- package/dist/types/bin.d.ts +1 -0
- package/dist/types/bin.js.map +1 -0
- package/dist/types/extract-hast/readability.d.ts +0 -9
- package/dist/types/extract-hast/readability.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/utils/bin-utils.d.ts +5 -0
- package/dist/types/utils/bin-utils.js.map +1 -0
- package/dist/utils/bin-utils.js +87 -0
- package/package.json +7 -7
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2023 inaridiy
|
|
3
|
+
Copyright (c) 2023 - present, inaridiy and webforai contributors
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -10,6 +10,7 @@ A library that provides a web interface for AI
|
|
|
10
10
|
- Ultra-precise Markdown segmentation based on AST
|
|
11
11
|
- Ultra-precise HTML retrieval functions using headless browsers
|
|
12
12
|
- The core functionality is edge-native (runs on Cloudflare Workers!!!)
|
|
13
|
+
- Command-line interface for easy use without coding
|
|
13
14
|
|
|
14
15
|
## Demo
|
|
15
16
|
|
|
@@ -18,14 +19,25 @@ There is a demo API for Html2Markdown deployed on CloudflareWorker. Please acces
|
|
|
18
19
|
- [NPM Package page](https://webforai.inaridiy.workers.dev/?url=https://www.npmjs.com/package/webforai)
|
|
19
20
|
- [Wikipedia of Cloudflare (AI Mode)](https://webforai.inaridiy.workers.dev/?url=https://en.wikipedia.org/wiki/Cloudflare&mode=ai)
|
|
20
21
|
|
|
21
|
-
##
|
|
22
|
-
|
|
23
|
-
Just install and execute scripts
|
|
22
|
+
## Installation
|
|
24
23
|
|
|
24
|
+
### As a library
|
|
25
|
+
To use WebforAI as a library in your project, install it along with playwright:
|
|
25
26
|
```bash
|
|
26
27
|
pnpm i webforai playwright
|
|
27
28
|
```
|
|
28
29
|
|
|
30
|
+
### As a CLI tool
|
|
31
|
+
To use WebforAI as a command-line tool, install it globally:
|
|
32
|
+
```bash
|
|
33
|
+
npm install -g webforai
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Quick Start
|
|
37
|
+
|
|
38
|
+
### Using as a library
|
|
39
|
+
Just install and execute scripts
|
|
40
|
+
|
|
29
41
|
```js
|
|
30
42
|
import { promises as fs } from "fs";
|
|
31
43
|
import { htmlToMarkdown, htmlToMdast } from "webforai";
|
|
@@ -41,6 +53,18 @@ await fs.writeFile("output.md", markdown);
|
|
|
41
53
|
|
|
42
54
|
other examples are in [examples](./examples/simple/src/index.ts)
|
|
43
55
|
|
|
56
|
+
### Using as a CLI tool
|
|
57
|
+
After installing globally, you can use the webforai command:
|
|
58
|
+
```bash
|
|
59
|
+
webforai https://www.npmjs.com/package/webforai output.md
|
|
60
|
+
```
|
|
61
|
+
This will fetch the HTML from the specified URL, convert it to Markdown, and save it to output.md.
|
|
62
|
+
|
|
63
|
+
For more CLI options, run:
|
|
64
|
+
```bash
|
|
65
|
+
webforai --help
|
|
66
|
+
```
|
|
67
|
+
|
|
44
68
|
## Examples
|
|
45
69
|
|
|
46
70
|
- [Simple Example](https://github.com/inaridiy/webforai/tree/main/examples/simple/src/index.ts)
|
|
@@ -68,3 +92,37 @@ Convert Mdast to Markdown. If `solveLinks` is specified, the relative links in t
|
|
|
68
92
|
|
|
69
93
|
**`loadHtml(url: string, options?: LoadHtmlOptions): Promise<string>`**
|
|
70
94
|
Load HTML from the specified URL. This function uses Playwright internally.
|
|
95
|
+
|
|
96
|
+
### CLI Commands
|
|
97
|
+
|
|
98
|
+
**`webforai <source?> <outputPath?> [options]`**
|
|
99
|
+
Converts the HTML at the specified URL or path to Markdown and saves it to an output file.
|
|
100
|
+
Arguments and options can be specified in the interactive interface even if they are not specified.
|
|
101
|
+
- **`source`**
|
|
102
|
+
The URL or path to the HTML file to convert.
|
|
103
|
+
- **`outputPath`**
|
|
104
|
+
The path to save the output Markdown file.
|
|
105
|
+
|
|
106
|
+
#### Options
|
|
107
|
+
- **`--mode <mode>`**
|
|
108
|
+
Specify the mode to use for conversion. Options are `default` and `ai`. Default is `default`.
|
|
109
|
+
- **`--loader <loader>`**
|
|
110
|
+
Specify the loader to use for fetching HTML. Options are `fetch`, `playwright` and `puppeteer`. Default is `fetch`.
|
|
111
|
+
- **`--baseUrl <baseUrl>`**
|
|
112
|
+
Specify the base URL to use for relative links in the output Markdown.
|
|
113
|
+
- **`-o --stdout`**
|
|
114
|
+
Output the converted Markdown to the console instead of saving it to a file.
|
|
115
|
+
- **`-d --debug`**
|
|
116
|
+
Enable debug mode. This will output additional information to the console.
|
|
117
|
+
|
|
118
|
+
**`webforai --help`**
|
|
119
|
+
Displays help information for the CLI tool.
|
|
120
|
+
|
|
121
|
+
## Contributing
|
|
122
|
+
1. Fork it!
|
|
123
|
+
2. Create your feature branch: `git checkout -b my-new-feature`
|
|
124
|
+
3. Add your changes: `git add .`
|
|
125
|
+
4. Commit your changes: `git commit -am 'Add some feature'`
|
|
126
|
+
5. Add a changelog: `pnpm changeset`
|
|
127
|
+
6. Push to the branch: `git push origin my-new-feature`
|
|
128
|
+
7. Submit a pull request :sunglasses:
|
package/dist/bin.js
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/bin.ts
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { cancel, confirm, intro, isCancel, outro, select, spinner, text } from "@clack/prompts";
|
|
7
|
+
import { program } from "commander";
|
|
8
|
+
import pc from "picocolors";
|
|
9
|
+
import packageInfo from "../package.json" assert { type: "json" };
|
|
10
|
+
import { htmlToMarkdown } from "./html-to-markdown.js";
|
|
11
|
+
import { loadHtml as playwrightLoadHtml } from "./loaders/playwright.js";
|
|
12
|
+
import { loadHtml as puppeteerLoadHtml } from "./loaders/puppeteer.js";
|
|
13
|
+
import { changeFileExtension, getNextAvailableFilePath, isUrl, urlToFilename } from "./utils/bin-utils.js";
|
|
14
|
+
var MODES = ["default", "ai"];
|
|
15
|
+
var LOADERS = ["fetch", "playwright", "puppeteer"];
|
|
16
|
+
var loadersHint = {
|
|
17
|
+
fetch: "Fetch HTML content from the given URL",
|
|
18
|
+
playwright: "Retrieve HTML content after rendering using Playwright; Playwright must be installed in advance.",
|
|
19
|
+
puppeteer: "Retrieve HTML content after rendering using Puppeteer; Puppeteer must be installed in advance."
|
|
20
|
+
};
|
|
21
|
+
var aiModeOptions = { linkAsText: true, tableAsText: true, hideImage: true };
|
|
22
|
+
var readabilityModeOptions = { linkAsText: false, tableAsText: false, hideImage: false };
|
|
23
|
+
program.name("webforai").description("CLI tool for ultra-precise HTML to Markdown conversion").version(packageInfo.version, "-v, --version", "output the current version").argument("[source]", "URL or path to process").argument("[outputPath]", "Path to output file or directory").option("--mode <mode>", `Processing mode (${MODES.join(", ")})`, MODES[0]).option("--loader <loader>", `Loader to use (${LOADERS.join(", ")})`, LOADERS[0]).option("--baseUrl <baseUrl>", "Base URL for relative links").option("-o, --stdout", "output to stdout").option("-d, --debug", "output extra debugging information").on("option:debug", () => {
|
|
24
|
+
process.env.DEBUG = "true";
|
|
25
|
+
}).action(
|
|
26
|
+
async (source, outputPath, options) => {
|
|
27
|
+
let finalSource;
|
|
28
|
+
let sourceIsUrl;
|
|
29
|
+
let finalOutputPath;
|
|
30
|
+
let finalMode;
|
|
31
|
+
let finalLoader = "fetch";
|
|
32
|
+
const isOutputFile = !options.stdout;
|
|
33
|
+
if (process.env.DEBUG) {
|
|
34
|
+
console.info("Arguments and options:");
|
|
35
|
+
console.table({
|
|
36
|
+
source,
|
|
37
|
+
outputPath,
|
|
38
|
+
...options
|
|
39
|
+
});
|
|
40
|
+
console.info("isOutputFile:", isOutputFile);
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
finalSource = await text({
|
|
44
|
+
message: "Enter the URL or html path to be converted to markdown:",
|
|
45
|
+
placeholder: "https://example.com",
|
|
46
|
+
initialValue: source,
|
|
47
|
+
validate: (value) => {
|
|
48
|
+
if (value.trim() === "") {
|
|
49
|
+
return "Source is required";
|
|
50
|
+
}
|
|
51
|
+
if (!isUrl(value)) {
|
|
52
|
+
if (!fs.existsSync(value)) {
|
|
53
|
+
return "It appears that you are specifying a local file, but the file cannot be found. hint: when specifying a url, start with http or https.";
|
|
54
|
+
}
|
|
55
|
+
if (fs.statSync(value).isDirectory()) {
|
|
56
|
+
return "You are specifying a local file, but you cannot specify a directory. hint: when specifying a url, start with http or https.";
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
if (isCancel(finalSource)) {
|
|
62
|
+
cancel("Canceled.");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
sourceIsUrl = isUrl(finalSource);
|
|
66
|
+
if (sourceIsUrl) {
|
|
67
|
+
finalLoader = await select({
|
|
68
|
+
message: "Select loader:",
|
|
69
|
+
options: LOADERS.map((mode) => ({ value: mode, label: mode, hint: loadersHint[mode] || "" })),
|
|
70
|
+
initialValue: options.loader && LOADERS.includes(options.loader) ? options.loader : "fetch"
|
|
71
|
+
});
|
|
72
|
+
if (isCancel(finalLoader)) {
|
|
73
|
+
cancel("Canceled.");
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (isOutputFile) {
|
|
78
|
+
finalOutputPath = await text({
|
|
79
|
+
message: "Enter the output file path:",
|
|
80
|
+
placeholder: "output.md",
|
|
81
|
+
initialValue: outputPath ? outputPath : sourceIsUrl ? `${urlToFilename(finalSource)}.md` : changeFileExtension(finalSource, "md"),
|
|
82
|
+
validate: (value) => {
|
|
83
|
+
if (value.trim() === "") {
|
|
84
|
+
return "Output path is required";
|
|
85
|
+
}
|
|
86
|
+
if (fs.existsSync(value) && fs.statSync(value).isDirectory()) {
|
|
87
|
+
return "No directory can be specified.";
|
|
88
|
+
}
|
|
89
|
+
if (!fs.existsSync(value) && value.endsWith("/")) {
|
|
90
|
+
return "No directory can be specified.";
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
if (isCancel(finalOutputPath)) {
|
|
95
|
+
cancel("Canceled.");
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (fs.existsSync(finalOutputPath)) {
|
|
99
|
+
const isOutputFileOverwrite = await confirm({
|
|
100
|
+
message: "The file already exists. Overwrite?",
|
|
101
|
+
initialValue: false
|
|
102
|
+
});
|
|
103
|
+
if (isCancel(isOutputFileOverwrite)) {
|
|
104
|
+
cancel("Canceled.");
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (isOutputFileOverwrite === false) {
|
|
108
|
+
finalOutputPath = await text({
|
|
109
|
+
message: "Enter the output file path:",
|
|
110
|
+
placeholder: "output.md",
|
|
111
|
+
initialValue: getNextAvailableFilePath(finalOutputPath),
|
|
112
|
+
validate: (value) => {
|
|
113
|
+
if (value.trim() === "") {
|
|
114
|
+
return "Output path is required";
|
|
115
|
+
}
|
|
116
|
+
if (fs.existsSync(value)) {
|
|
117
|
+
return "The file already exists";
|
|
118
|
+
}
|
|
119
|
+
if (!fs.existsSync(value) && value.endsWith("/")) {
|
|
120
|
+
return "No directory can be specified.";
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
if (isCancel(finalOutputPath)) {
|
|
125
|
+
cancel("Canceled.");
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
} else {
|
|
131
|
+
finalOutputPath = "";
|
|
132
|
+
}
|
|
133
|
+
finalMode = await select({
|
|
134
|
+
message: "Select processing mode:",
|
|
135
|
+
options: MODES.map((mode) => ({ value: mode, label: mode })),
|
|
136
|
+
initialValue: options.mode && MODES.includes(options.mode) ? options.mode : "default"
|
|
137
|
+
});
|
|
138
|
+
if (isCancel(finalMode)) {
|
|
139
|
+
cancel("Canceled.");
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
} catch (e) {
|
|
143
|
+
const error = e;
|
|
144
|
+
console.error(pc.red("An error occurred while processing the given value:"), error.message);
|
|
145
|
+
if (process.env.DEBUG) {
|
|
146
|
+
console.error(error.stack);
|
|
147
|
+
}
|
|
148
|
+
process.exit(1);
|
|
149
|
+
}
|
|
150
|
+
if (process.env.DEBUG) {
|
|
151
|
+
console.info("Processing with the following options:");
|
|
152
|
+
console.table({ finalSource, sourceIsUrl, isOutputFile, finalOutputPath, finalMode, finalLoader });
|
|
153
|
+
}
|
|
154
|
+
let content;
|
|
155
|
+
const loadSpinner = spinner();
|
|
156
|
+
try {
|
|
157
|
+
if (sourceIsUrl) {
|
|
158
|
+
loadSpinner.start("Downloading content.");
|
|
159
|
+
if (finalLoader === "playwright") {
|
|
160
|
+
content = await playwrightLoadHtml(finalSource);
|
|
161
|
+
} else if (finalLoader === "puppeteer") {
|
|
162
|
+
content = await puppeteerLoadHtml(finalSource);
|
|
163
|
+
} else {
|
|
164
|
+
const response = await fetch(finalSource);
|
|
165
|
+
content = await response.text();
|
|
166
|
+
}
|
|
167
|
+
loadSpinner.stop("Content download is complete!");
|
|
168
|
+
} else {
|
|
169
|
+
loadSpinner.start("Retrieving content.");
|
|
170
|
+
if (!fs.existsSync(finalSource)) {
|
|
171
|
+
console.error(pc.red("The file does not exist"));
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
const stats = fs.statSync(finalSource);
|
|
175
|
+
if (!stats.isFile()) {
|
|
176
|
+
console.error(pc.red("The source must be a file"));
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
content = fs.readFileSync(finalSource, "utf-8");
|
|
180
|
+
loadSpinner.stop("Content retrieval is complete!");
|
|
181
|
+
}
|
|
182
|
+
} catch (e) {
|
|
183
|
+
const error = e;
|
|
184
|
+
loadSpinner.stop(pc.red("An error occurred while retrieving content"));
|
|
185
|
+
console.error(error.message);
|
|
186
|
+
if (process.env.DEBUG) {
|
|
187
|
+
console.error(error.stack);
|
|
188
|
+
}
|
|
189
|
+
process.exit(1);
|
|
190
|
+
}
|
|
191
|
+
if (process.env.DEBUG) {
|
|
192
|
+
console.info("Content:");
|
|
193
|
+
console.info(content);
|
|
194
|
+
}
|
|
195
|
+
const convertSpinner = spinner();
|
|
196
|
+
try {
|
|
197
|
+
convertSpinner.start("Converting content to markdown.");
|
|
198
|
+
const markdown = htmlToMarkdown(content, {
|
|
199
|
+
...sourceIsUrl || !!options.baseUrl && options.baseUrl.trim() !== "" ? { baseUrl: options.baseUrl || finalSource } : {},
|
|
200
|
+
...finalMode === "ai" ? aiModeOptions : readabilityModeOptions
|
|
201
|
+
});
|
|
202
|
+
if (process.env.DEBUG) {
|
|
203
|
+
console.info("Markdown:");
|
|
204
|
+
console.info(markdown);
|
|
205
|
+
}
|
|
206
|
+
if (isOutputFile) {
|
|
207
|
+
const directory = path.dirname(finalOutputPath);
|
|
208
|
+
if (!fs.existsSync(directory)) {
|
|
209
|
+
fs.mkdirSync(directory, { recursive: true });
|
|
210
|
+
}
|
|
211
|
+
fs.writeFileSync(finalOutputPath, markdown);
|
|
212
|
+
convertSpinner.stop("Markdown conversion is complete!");
|
|
213
|
+
outro(`Converted successfully to markdown! Output saved to: ${path.resolve(finalOutputPath)} \u{1F389}`);
|
|
214
|
+
} else {
|
|
215
|
+
convertSpinner.stop("Markdown conversion is complete!");
|
|
216
|
+
outro("Converted successfully to markdown\u{1F389}");
|
|
217
|
+
console.log(`
|
|
218
|
+
|
|
219
|
+
${markdown}`);
|
|
220
|
+
}
|
|
221
|
+
} catch (e) {
|
|
222
|
+
const error = e;
|
|
223
|
+
convertSpinner.stop(pc.red("An error occurred while converting and saving the markdown"));
|
|
224
|
+
console.error(error.message);
|
|
225
|
+
if (process.env.DEBUG) {
|
|
226
|
+
console.error(error.stack);
|
|
227
|
+
}
|
|
228
|
+
process.exit(1);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
);
|
|
232
|
+
intro(pc.inverse(`webforai CLI version ${packageInfo.version}`));
|
|
233
|
+
program.parse();
|
package/dist/cjs/bin.js
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
22
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
+
mod
|
|
24
|
+
));
|
|
25
|
+
var import_node_fs = __toESM(require("node:fs"), 1);
|
|
26
|
+
var import_node_path = __toESM(require("node:path"), 1);
|
|
27
|
+
var import_prompts = require("@clack/prompts");
|
|
28
|
+
var import_commander = require("commander");
|
|
29
|
+
var import_picocolors = __toESM(require("picocolors"), 1);
|
|
30
|
+
var import_package = __toESM(require("../package.json"), 1);
|
|
31
|
+
var import_html_to_markdown = require("./html-to-markdown");
|
|
32
|
+
var import_playwright = require("./loaders/playwright");
|
|
33
|
+
var import_puppeteer = require("./loaders/puppeteer");
|
|
34
|
+
var import_bin_utils = require("./utils/bin-utils");
|
|
35
|
+
const MODES = ["default", "ai"];
|
|
36
|
+
const LOADERS = ["fetch", "playwright", "puppeteer"];
|
|
37
|
+
const loadersHint = {
|
|
38
|
+
fetch: "Fetch HTML content from the given URL",
|
|
39
|
+
playwright: "Retrieve HTML content after rendering using Playwright; Playwright must be installed in advance.",
|
|
40
|
+
puppeteer: "Retrieve HTML content after rendering using Puppeteer; Puppeteer must be installed in advance."
|
|
41
|
+
};
|
|
42
|
+
const aiModeOptions = { linkAsText: true, tableAsText: true, hideImage: true };
|
|
43
|
+
const readabilityModeOptions = { linkAsText: false, tableAsText: false, hideImage: false };
|
|
44
|
+
import_commander.program.name("webforai").description("CLI tool for ultra-precise HTML to Markdown conversion").version(import_package.default.version, "-v, --version", "output the current version").argument("[source]", "URL or path to process").argument("[outputPath]", "Path to output file or directory").option("--mode <mode>", `Processing mode (${MODES.join(", ")})`, MODES[0]).option("--loader <loader>", `Loader to use (${LOADERS.join(", ")})`, LOADERS[0]).option("--baseUrl <baseUrl>", "Base URL for relative links").option("-o, --stdout", "output to stdout").option("-d, --debug", "output extra debugging information").on("option:debug", () => {
|
|
45
|
+
process.env.DEBUG = "true";
|
|
46
|
+
}).action(
|
|
47
|
+
async (source, outputPath, options) => {
|
|
48
|
+
let finalSource;
|
|
49
|
+
let sourceIsUrl;
|
|
50
|
+
let finalOutputPath;
|
|
51
|
+
let finalMode;
|
|
52
|
+
let finalLoader = "fetch";
|
|
53
|
+
const isOutputFile = !options.stdout;
|
|
54
|
+
if (process.env.DEBUG) {
|
|
55
|
+
console.info("Arguments and options:");
|
|
56
|
+
console.table({
|
|
57
|
+
source,
|
|
58
|
+
outputPath,
|
|
59
|
+
...options
|
|
60
|
+
});
|
|
61
|
+
console.info("isOutputFile:", isOutputFile);
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
finalSource = await (0, import_prompts.text)({
|
|
65
|
+
message: "Enter the URL or html path to be converted to markdown:",
|
|
66
|
+
placeholder: "https://example.com",
|
|
67
|
+
initialValue: source,
|
|
68
|
+
validate: (value) => {
|
|
69
|
+
if (value.trim() === "") {
|
|
70
|
+
return "Source is required";
|
|
71
|
+
}
|
|
72
|
+
if (!(0, import_bin_utils.isUrl)(value)) {
|
|
73
|
+
if (!import_node_fs.default.existsSync(value)) {
|
|
74
|
+
return "It appears that you are specifying a local file, but the file cannot be found. hint: when specifying a url, start with http or https.";
|
|
75
|
+
}
|
|
76
|
+
if (import_node_fs.default.statSync(value).isDirectory()) {
|
|
77
|
+
return "You are specifying a local file, but you cannot specify a directory. hint: when specifying a url, start with http or https.";
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
if ((0, import_prompts.isCancel)(finalSource)) {
|
|
83
|
+
(0, import_prompts.cancel)("Canceled.");
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
sourceIsUrl = (0, import_bin_utils.isUrl)(finalSource);
|
|
87
|
+
if (sourceIsUrl) {
|
|
88
|
+
finalLoader = await (0, import_prompts.select)({
|
|
89
|
+
message: "Select loader:",
|
|
90
|
+
options: LOADERS.map((mode) => ({ value: mode, label: mode, hint: loadersHint[mode] || "" })),
|
|
91
|
+
initialValue: options.loader && LOADERS.includes(options.loader) ? options.loader : "fetch"
|
|
92
|
+
});
|
|
93
|
+
if ((0, import_prompts.isCancel)(finalLoader)) {
|
|
94
|
+
(0, import_prompts.cancel)("Canceled.");
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (isOutputFile) {
|
|
99
|
+
finalOutputPath = await (0, import_prompts.text)({
|
|
100
|
+
message: "Enter the output file path:",
|
|
101
|
+
placeholder: "output.md",
|
|
102
|
+
initialValue: outputPath ? outputPath : sourceIsUrl ? `${(0, import_bin_utils.urlToFilename)(finalSource)}.md` : (0, import_bin_utils.changeFileExtension)(finalSource, "md"),
|
|
103
|
+
validate: (value) => {
|
|
104
|
+
if (value.trim() === "") {
|
|
105
|
+
return "Output path is required";
|
|
106
|
+
}
|
|
107
|
+
if (import_node_fs.default.existsSync(value) && import_node_fs.default.statSync(value).isDirectory()) {
|
|
108
|
+
return "No directory can be specified.";
|
|
109
|
+
}
|
|
110
|
+
if (!import_node_fs.default.existsSync(value) && value.endsWith("/")) {
|
|
111
|
+
return "No directory can be specified.";
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
if ((0, import_prompts.isCancel)(finalOutputPath)) {
|
|
116
|
+
(0, import_prompts.cancel)("Canceled.");
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (import_node_fs.default.existsSync(finalOutputPath)) {
|
|
120
|
+
const isOutputFileOverwrite = await (0, import_prompts.confirm)({
|
|
121
|
+
message: "The file already exists. Overwrite?",
|
|
122
|
+
initialValue: false
|
|
123
|
+
});
|
|
124
|
+
if ((0, import_prompts.isCancel)(isOutputFileOverwrite)) {
|
|
125
|
+
(0, import_prompts.cancel)("Canceled.");
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (isOutputFileOverwrite === false) {
|
|
129
|
+
finalOutputPath = await (0, import_prompts.text)({
|
|
130
|
+
message: "Enter the output file path:",
|
|
131
|
+
placeholder: "output.md",
|
|
132
|
+
initialValue: (0, import_bin_utils.getNextAvailableFilePath)(finalOutputPath),
|
|
133
|
+
validate: (value) => {
|
|
134
|
+
if (value.trim() === "") {
|
|
135
|
+
return "Output path is required";
|
|
136
|
+
}
|
|
137
|
+
if (import_node_fs.default.existsSync(value)) {
|
|
138
|
+
return "The file already exists";
|
|
139
|
+
}
|
|
140
|
+
if (!import_node_fs.default.existsSync(value) && value.endsWith("/")) {
|
|
141
|
+
return "No directory can be specified.";
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
if ((0, import_prompts.isCancel)(finalOutputPath)) {
|
|
146
|
+
(0, import_prompts.cancel)("Canceled.");
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
} else {
|
|
152
|
+
finalOutputPath = "";
|
|
153
|
+
}
|
|
154
|
+
finalMode = await (0, import_prompts.select)({
|
|
155
|
+
message: "Select processing mode:",
|
|
156
|
+
options: MODES.map((mode) => ({ value: mode, label: mode })),
|
|
157
|
+
initialValue: options.mode && MODES.includes(options.mode) ? options.mode : "default"
|
|
158
|
+
});
|
|
159
|
+
if ((0, import_prompts.isCancel)(finalMode)) {
|
|
160
|
+
(0, import_prompts.cancel)("Canceled.");
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
} catch (e) {
|
|
164
|
+
const error = e;
|
|
165
|
+
console.error(import_picocolors.default.red("An error occurred while processing the given value:"), error.message);
|
|
166
|
+
if (process.env.DEBUG) {
|
|
167
|
+
console.error(error.stack);
|
|
168
|
+
}
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
if (process.env.DEBUG) {
|
|
172
|
+
console.info("Processing with the following options:");
|
|
173
|
+
console.table({ finalSource, sourceIsUrl, isOutputFile, finalOutputPath, finalMode, finalLoader });
|
|
174
|
+
}
|
|
175
|
+
let content;
|
|
176
|
+
const loadSpinner = (0, import_prompts.spinner)();
|
|
177
|
+
try {
|
|
178
|
+
if (sourceIsUrl) {
|
|
179
|
+
loadSpinner.start("Downloading content.");
|
|
180
|
+
if (finalLoader === "playwright") {
|
|
181
|
+
content = await (0, import_playwright.loadHtml)(finalSource);
|
|
182
|
+
} else if (finalLoader === "puppeteer") {
|
|
183
|
+
content = await (0, import_puppeteer.loadHtml)(finalSource);
|
|
184
|
+
} else {
|
|
185
|
+
const response = await fetch(finalSource);
|
|
186
|
+
content = await response.text();
|
|
187
|
+
}
|
|
188
|
+
loadSpinner.stop("Content download is complete!");
|
|
189
|
+
} else {
|
|
190
|
+
loadSpinner.start("Retrieving content.");
|
|
191
|
+
if (!import_node_fs.default.existsSync(finalSource)) {
|
|
192
|
+
console.error(import_picocolors.default.red("The file does not exist"));
|
|
193
|
+
process.exit(1);
|
|
194
|
+
}
|
|
195
|
+
const stats = import_node_fs.default.statSync(finalSource);
|
|
196
|
+
if (!stats.isFile()) {
|
|
197
|
+
console.error(import_picocolors.default.red("The source must be a file"));
|
|
198
|
+
process.exit(1);
|
|
199
|
+
}
|
|
200
|
+
content = import_node_fs.default.readFileSync(finalSource, "utf-8");
|
|
201
|
+
loadSpinner.stop("Content retrieval is complete!");
|
|
202
|
+
}
|
|
203
|
+
} catch (e) {
|
|
204
|
+
const error = e;
|
|
205
|
+
loadSpinner.stop(import_picocolors.default.red("An error occurred while retrieving content"));
|
|
206
|
+
console.error(error.message);
|
|
207
|
+
if (process.env.DEBUG) {
|
|
208
|
+
console.error(error.stack);
|
|
209
|
+
}
|
|
210
|
+
process.exit(1);
|
|
211
|
+
}
|
|
212
|
+
if (process.env.DEBUG) {
|
|
213
|
+
console.info("Content:");
|
|
214
|
+
console.info(content);
|
|
215
|
+
}
|
|
216
|
+
const convertSpinner = (0, import_prompts.spinner)();
|
|
217
|
+
try {
|
|
218
|
+
convertSpinner.start("Converting content to markdown.");
|
|
219
|
+
const markdown = (0, import_html_to_markdown.htmlToMarkdown)(content, {
|
|
220
|
+
...sourceIsUrl || !!options.baseUrl && options.baseUrl.trim() !== "" ? { baseUrl: options.baseUrl || finalSource } : {},
|
|
221
|
+
...finalMode === "ai" ? aiModeOptions : readabilityModeOptions
|
|
222
|
+
});
|
|
223
|
+
if (process.env.DEBUG) {
|
|
224
|
+
console.info("Markdown:");
|
|
225
|
+
console.info(markdown);
|
|
226
|
+
}
|
|
227
|
+
if (isOutputFile) {
|
|
228
|
+
const directory = import_node_path.default.dirname(finalOutputPath);
|
|
229
|
+
if (!import_node_fs.default.existsSync(directory)) {
|
|
230
|
+
import_node_fs.default.mkdirSync(directory, { recursive: true });
|
|
231
|
+
}
|
|
232
|
+
import_node_fs.default.writeFileSync(finalOutputPath, markdown);
|
|
233
|
+
convertSpinner.stop("Markdown conversion is complete!");
|
|
234
|
+
(0, import_prompts.outro)(`Converted successfully to markdown! Output saved to: ${import_node_path.default.resolve(finalOutputPath)} \u{1F389}`);
|
|
235
|
+
} else {
|
|
236
|
+
convertSpinner.stop("Markdown conversion is complete!");
|
|
237
|
+
(0, import_prompts.outro)("Converted successfully to markdown\u{1F389}");
|
|
238
|
+
console.log(`
|
|
239
|
+
|
|
240
|
+
${markdown}`);
|
|
241
|
+
}
|
|
242
|
+
} catch (e) {
|
|
243
|
+
const error = e;
|
|
244
|
+
convertSpinner.stop(import_picocolors.default.red("An error occurred while converting and saving the markdown"));
|
|
245
|
+
console.error(error.message);
|
|
246
|
+
if (process.env.DEBUG) {
|
|
247
|
+
console.error(error.stack);
|
|
248
|
+
}
|
|
249
|
+
process.exit(1);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
);
|
|
253
|
+
(0, import_prompts.intro)(import_picocolors.default.inverse(`webforai CLI version ${import_package.default.version}`));
|
|
254
|
+
import_commander.program.parse();
|
|
@@ -24,7 +24,6 @@ module.exports = __toCommonJS(readability_exports);
|
|
|
24
24
|
var import_hast_util_select = require("hast-util-select");
|
|
25
25
|
var import_hast_util_to_string = require("hast-util-to-string");
|
|
26
26
|
var import_unist_util_filter = require("unist-util-filter");
|
|
27
|
-
var import_unist_util_parents = require("unist-util-parents");
|
|
28
27
|
var import_utils = require("./utils");
|
|
29
28
|
const UNLIKELY_ROLES = ["menu", "menubar", "complementary", "navigation", "alert", "alertdialog", "dialog"];
|
|
30
29
|
const REGEXPS = {
|
|
@@ -135,8 +134,8 @@ const removeEmptyFilter = (node) => {
|
|
|
135
134
|
const readabilityExtractHast = (hast) => {
|
|
136
135
|
const lang = String((0, import_hast_util_select.select)("html", hast)?.properties.lang || tryGetLang(hast) || "en");
|
|
137
136
|
const body = (0, import_hast_util_select.select)("body", hast) ?? hast;
|
|
138
|
-
const
|
|
139
|
-
const baseFilterd = (0, import_unist_util_filter.filter)(
|
|
137
|
+
const bodyText = (0, import_hast_util_to_string.toString)(body);
|
|
138
|
+
const baseFilterd = (0, import_unist_util_filter.filter)(body, (node) => {
|
|
140
139
|
if (!metadataFilter(node)) {
|
|
141
140
|
return false;
|
|
142
141
|
}
|
|
@@ -148,30 +147,31 @@ const readabilityExtractHast = (hast) => {
|
|
|
148
147
|
if (!baseFilterd) {
|
|
149
148
|
return { type: "root", children: [] };
|
|
150
149
|
}
|
|
151
|
-
const
|
|
150
|
+
const baseFilterdText = (0, import_hast_util_to_string.toString)(baseFilterd);
|
|
151
|
+
let [baseTree, baseText] = baseFilterdText.length > bodyText.length / 3 || baseFilterdText.length > 5e3 ? [baseFilterd, baseFilterdText] : [body, bodyText];
|
|
152
152
|
let minimalLength = lang in BASE_MINIMAL_LENGTH ? BASE_MINIMAL_LENGTH[lang] : 500;
|
|
153
153
|
if (baseText.length < minimalLength) {
|
|
154
154
|
minimalLength = Math.max(0, baseText.length - 200);
|
|
155
155
|
}
|
|
156
|
-
let bodyTree = baseFilterd;
|
|
157
156
|
for (const selector of BODY_SELECTORS) {
|
|
158
|
-
const
|
|
159
|
-
const
|
|
160
|
-
if (
|
|
157
|
+
const content = { type: "root", children: (0, import_hast_util_select.selectAll)(selector, baseFilterd) };
|
|
158
|
+
const contentText = (0, import_hast_util_to_string.toString)(content);
|
|
159
|
+
if (contentText.length < 25) {
|
|
161
160
|
continue;
|
|
162
161
|
}
|
|
163
|
-
const links = (0, import_hast_util_select.selectAll)("a",
|
|
162
|
+
const links = (0, import_hast_util_select.selectAll)("a", content);
|
|
164
163
|
const linkText = links.map((link) => (0, import_hast_util_to_string.toString)(link)).join("");
|
|
165
164
|
const linkDensity = linkText.length / bodyText.length;
|
|
166
165
|
if (linkDensity > 0.4) {
|
|
167
166
|
continue;
|
|
168
167
|
}
|
|
169
|
-
if (
|
|
170
|
-
|
|
168
|
+
if (contentText.length > minimalLength) {
|
|
169
|
+
baseTree = content;
|
|
170
|
+
baseText = contentText;
|
|
171
171
|
break;
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
|
-
const
|
|
174
|
+
const finalFilteredTree = (0, import_unist_util_filter.filter)(baseTree, (node) => {
|
|
175
175
|
if (!removeEmptyFilter(node)) {
|
|
176
176
|
return false;
|
|
177
177
|
}
|
|
@@ -180,6 +180,7 @@ const readabilityExtractHast = (hast) => {
|
|
|
180
180
|
}
|
|
181
181
|
return true;
|
|
182
182
|
});
|
|
183
|
+
const finalTree = (0, import_hast_util_to_string.toString)(finalFilteredTree).length > baseText.length / 3 ? finalFilteredTree : baseTree;
|
|
183
184
|
return finalTree;
|
|
184
185
|
};
|
|
185
186
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -131,14 +131,14 @@ Cell 1 Cell 2`;
|
|
|
131
131
|
(0, import_vitest.describe)("htmlToMarkdown E2E", () => {
|
|
132
132
|
(0, import_vitest.it)("should convert npm README to Markdown ", async () => {
|
|
133
133
|
const html2 = await (0, import_fetch.loadHtml)("https://www.npmjs.com/package/webforai");
|
|
134
|
-
const markdown = (0, import_html_to_markdown.htmlToMarkdown)(html2
|
|
134
|
+
const markdown = (0, import_html_to_markdown.htmlToMarkdown)(html2);
|
|
135
135
|
const original = await import("../README.md?raw");
|
|
136
136
|
const d = (0, import_fastest_levenshtein.distance)(markdown, original.default);
|
|
137
|
-
(0, import_vitest.expect)(d).lte(
|
|
137
|
+
(0, import_vitest.expect)(d).lte(200);
|
|
138
138
|
});
|
|
139
139
|
(0, import_vitest.it)("should convert GitHub README to Markdown ", async () => {
|
|
140
140
|
const html2 = await (0, import_fetch.loadHtml)("https://github.com/inaridiy/webforai");
|
|
141
|
-
const markdown = (0, import_html_to_markdown.htmlToMarkdown)(html2
|
|
141
|
+
const markdown = (0, import_html_to_markdown.htmlToMarkdown)(html2);
|
|
142
142
|
const original = await import("../../../README.md?raw");
|
|
143
143
|
const d = (0, import_fastest_levenshtein.distance)(markdown, original.default);
|
|
144
144
|
(0, import_vitest.expect)(d).lte(200);
|
package/dist/cjs/index.js
CHANGED
|
@@ -18,6 +18,8 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var src_exports = {};
|
|
20
20
|
__export(src_exports, {
|
|
21
|
+
DEFAULT_EXTRACT_HAST: () => import_extract_hast.DEFAULT_EXTRACT_HAST,
|
|
22
|
+
PRESET_EXTRACT_HAST: () => import_extract_hast.PRESET_EXTRACT_HAST,
|
|
21
23
|
htmlToMarkdown: () => import_html_to_markdown.htmlToMarkdown,
|
|
22
24
|
htmlToMdast: () => import_html_to_mdast.htmlToMdast,
|
|
23
25
|
mdastSplitter: () => import_md_splitter.mdastSplitter,
|
|
@@ -28,8 +30,11 @@ var import_html_to_markdown = require("./html-to-markdown");
|
|
|
28
30
|
var import_md_splitter = require("./md-splitter");
|
|
29
31
|
var import_html_to_mdast = require("./html-to-mdast");
|
|
30
32
|
var import_mdast_to_markdown = require("./mdast-to-markdown");
|
|
33
|
+
var import_extract_hast = require("./extract-hast/index");
|
|
31
34
|
// Annotate the CommonJS export names for ESM import in node:
|
|
32
35
|
0 && (module.exports = {
|
|
36
|
+
DEFAULT_EXTRACT_HAST,
|
|
37
|
+
PRESET_EXTRACT_HAST,
|
|
33
38
|
htmlToMarkdown,
|
|
34
39
|
htmlToMdast,
|
|
35
40
|
mdastSplitter,
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var bin_utils_exports = {};
|
|
30
|
+
__export(bin_utils_exports, {
|
|
31
|
+
changeFileExtension: () => changeFileExtension,
|
|
32
|
+
getNextAvailableFilePath: () => getNextAvailableFilePath,
|
|
33
|
+
isUrl: () => isUrl,
|
|
34
|
+
logError: () => logError,
|
|
35
|
+
urlToFilename: () => urlToFilename
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(bin_utils_exports);
|
|
38
|
+
var import_node_fs = __toESM(require("node:fs"), 1);
|
|
39
|
+
var import_node_path = __toESM(require("node:path"), 1);
|
|
40
|
+
var import_prompts = require("@clack/prompts");
|
|
41
|
+
function logError(error) {
|
|
42
|
+
import_prompts.log.error("An error occurred during processing");
|
|
43
|
+
console.error(error.message);
|
|
44
|
+
}
|
|
45
|
+
function isUrl(str) {
|
|
46
|
+
try {
|
|
47
|
+
new URL(str);
|
|
48
|
+
return true;
|
|
49
|
+
} catch {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function getNextAvailableFilePath(filePath) {
|
|
54
|
+
const parsedPath = import_node_path.default.parse(filePath);
|
|
55
|
+
const directory = parsedPath.dir;
|
|
56
|
+
const fullName = parsedPath.base;
|
|
57
|
+
const [firstPart, ...restParts] = fullName.split(".");
|
|
58
|
+
const restName = restParts.length > 0 ? `.${restParts.join(".")}` : "";
|
|
59
|
+
const baseName = firstPart.replace(/_\d+$/, "");
|
|
60
|
+
let counter = 1;
|
|
61
|
+
let nextFilePath = filePath;
|
|
62
|
+
while (import_node_fs.default.existsSync(nextFilePath)) {
|
|
63
|
+
const match = firstPart.match(/_(\d+)$/);
|
|
64
|
+
if (match) {
|
|
65
|
+
counter = Number.parseInt(match[1], 10) + 1;
|
|
66
|
+
}
|
|
67
|
+
const newName = `${baseName}_${counter}${restName}`;
|
|
68
|
+
nextFilePath = import_node_path.default.join(directory, newName);
|
|
69
|
+
counter++;
|
|
70
|
+
}
|
|
71
|
+
return nextFilePath;
|
|
72
|
+
}
|
|
73
|
+
function changeFileExtension(filePath, newExtension) {
|
|
74
|
+
const parsedPath = filePath.split("/");
|
|
75
|
+
const fileName = parsedPath[parsedPath.length - 1];
|
|
76
|
+
const formattedNewExtension = newExtension.startsWith(".") ? newExtension : `.${newExtension}`;
|
|
77
|
+
if (fileName.startsWith(".")) {
|
|
78
|
+
const parts = fileName.split(".");
|
|
79
|
+
if (parts.length === 2) {
|
|
80
|
+
return parsedPath.slice(0, -1).concat(`${fileName}${formattedNewExtension}`).join("/");
|
|
81
|
+
}
|
|
82
|
+
parts[parts.length - 1] = newExtension.replace(/^\./, "");
|
|
83
|
+
return parsedPath.slice(0, -1).concat(parts.join(".")).join("/");
|
|
84
|
+
}
|
|
85
|
+
const lastDotIndex = fileName.lastIndexOf(".");
|
|
86
|
+
const baseName = lastDotIndex !== -1 ? fileName.slice(0, lastDotIndex) : fileName;
|
|
87
|
+
const newFileName = `${baseName}${formattedNewExtension}`;
|
|
88
|
+
parsedPath[parsedPath.length - 1] = newFileName;
|
|
89
|
+
return parsedPath.join("/");
|
|
90
|
+
}
|
|
91
|
+
function urlToFilename(url) {
|
|
92
|
+
try {
|
|
93
|
+
const urlObj = new URL(url);
|
|
94
|
+
const domainParts = urlObj.hostname.split(".").reverse().reduce((acc, part, index) => {
|
|
95
|
+
if (index === 0) {
|
|
96
|
+
return acc;
|
|
97
|
+
}
|
|
98
|
+
if (acc.length >= 2) {
|
|
99
|
+
return acc;
|
|
100
|
+
}
|
|
101
|
+
if (part === "www") {
|
|
102
|
+
return acc;
|
|
103
|
+
}
|
|
104
|
+
return [part, ...acc];
|
|
105
|
+
}, []);
|
|
106
|
+
const domainString = domainParts.reverse().join("-");
|
|
107
|
+
const pathParts = urlObj.pathname.split("/").filter(Boolean);
|
|
108
|
+
const relevantPathParts = pathParts.slice(-2);
|
|
109
|
+
const pathString = relevantPathParts.map((part) => decodeURIComponent(part)).join("-");
|
|
110
|
+
let filename = [domainString, pathString].filter(Boolean).join("-");
|
|
111
|
+
filename = filename.toLowerCase().replace(/[<>:"/\\|?*\x00-\x1F]/g, "").replace(/[\s.]+/g, "-").replace(/^-+|-+$/g, "");
|
|
112
|
+
return filename || "output";
|
|
113
|
+
} catch {
|
|
114
|
+
return "output";
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
118
|
+
0 && (module.exports = {
|
|
119
|
+
changeFileExtension,
|
|
120
|
+
getNextAvailableFilePath,
|
|
121
|
+
isUrl,
|
|
122
|
+
logError,
|
|
123
|
+
urlToFilename
|
|
124
|
+
});
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import { select, selectAll } from "hast-util-select";
|
|
3
3
|
import { toString as hastToString } from "hast-util-to-string";
|
|
4
4
|
import { filter } from "unist-util-filter";
|
|
5
|
-
import { parents } from "unist-util-parents";
|
|
6
5
|
import { classnames, hasAncestors, isStrInclude, matchString } from "./utils.js";
|
|
7
6
|
var UNLIKELY_ROLES = ["menu", "menubar", "complementary", "navigation", "alert", "alertdialog", "dialog"];
|
|
8
7
|
var REGEXPS = {
|
|
@@ -113,8 +112,8 @@ var removeEmptyFilter = (node) => {
|
|
|
113
112
|
var readabilityExtractHast = (hast) => {
|
|
114
113
|
const lang = String(select("html", hast)?.properties.lang || tryGetLang(hast) || "en");
|
|
115
114
|
const body = select("body", hast) ?? hast;
|
|
116
|
-
const
|
|
117
|
-
const baseFilterd = filter(
|
|
115
|
+
const bodyText = hastToString(body);
|
|
116
|
+
const baseFilterd = filter(body, (node) => {
|
|
118
117
|
if (!metadataFilter(node)) {
|
|
119
118
|
return false;
|
|
120
119
|
}
|
|
@@ -126,30 +125,31 @@ var readabilityExtractHast = (hast) => {
|
|
|
126
125
|
if (!baseFilterd) {
|
|
127
126
|
return { type: "root", children: [] };
|
|
128
127
|
}
|
|
129
|
-
const
|
|
128
|
+
const baseFilterdText = hastToString(baseFilterd);
|
|
129
|
+
let [baseTree, baseText] = baseFilterdText.length > bodyText.length / 3 || baseFilterdText.length > 5e3 ? [baseFilterd, baseFilterdText] : [body, bodyText];
|
|
130
130
|
let minimalLength = lang in BASE_MINIMAL_LENGTH ? BASE_MINIMAL_LENGTH[lang] : 500;
|
|
131
131
|
if (baseText.length < minimalLength) {
|
|
132
132
|
minimalLength = Math.max(0, baseText.length - 200);
|
|
133
133
|
}
|
|
134
|
-
let bodyTree = baseFilterd;
|
|
135
134
|
for (const selector of BODY_SELECTORS) {
|
|
136
|
-
const
|
|
137
|
-
const
|
|
138
|
-
if (
|
|
135
|
+
const content = { type: "root", children: selectAll(selector, baseFilterd) };
|
|
136
|
+
const contentText = hastToString(content);
|
|
137
|
+
if (contentText.length < 25) {
|
|
139
138
|
continue;
|
|
140
139
|
}
|
|
141
|
-
const links = selectAll("a",
|
|
140
|
+
const links = selectAll("a", content);
|
|
142
141
|
const linkText = links.map((link) => hastToString(link)).join("");
|
|
143
142
|
const linkDensity = linkText.length / bodyText.length;
|
|
144
143
|
if (linkDensity > 0.4) {
|
|
145
144
|
continue;
|
|
146
145
|
}
|
|
147
|
-
if (
|
|
148
|
-
|
|
146
|
+
if (contentText.length > minimalLength) {
|
|
147
|
+
baseTree = content;
|
|
148
|
+
baseText = contentText;
|
|
149
149
|
break;
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
|
-
const
|
|
152
|
+
const finalFilteredTree = filter(baseTree, (node) => {
|
|
153
153
|
if (!removeEmptyFilter(node)) {
|
|
154
154
|
return false;
|
|
155
155
|
}
|
|
@@ -158,6 +158,7 @@ var readabilityExtractHast = (hast) => {
|
|
|
158
158
|
}
|
|
159
159
|
return true;
|
|
160
160
|
});
|
|
161
|
+
const finalTree = hastToString(finalFilteredTree).length > baseText.length / 3 ? finalFilteredTree : baseTree;
|
|
161
162
|
return finalTree;
|
|
162
163
|
};
|
|
163
164
|
export {
|
|
@@ -109,14 +109,14 @@ describe("htmlToMarkdown", () => {
|
|
|
109
109
|
describe("htmlToMarkdown E2E", () => {
|
|
110
110
|
it("should convert npm README to Markdown ", async () => {
|
|
111
111
|
const html2 = await loadHtml("https://www.npmjs.com/package/webforai");
|
|
112
|
-
const markdown = htmlToMarkdown(html2
|
|
112
|
+
const markdown = htmlToMarkdown(html2);
|
|
113
113
|
const original = await import("../README.md?raw");
|
|
114
114
|
const d = distance(markdown, original.default);
|
|
115
|
-
expect(d).lte(
|
|
115
|
+
expect(d).lte(200);
|
|
116
116
|
});
|
|
117
117
|
it("should convert GitHub README to Markdown ", async () => {
|
|
118
118
|
const html2 = await loadHtml("https://github.com/inaridiy/webforai");
|
|
119
|
-
const markdown = htmlToMarkdown(html2
|
|
119
|
+
const markdown = htmlToMarkdown(html2);
|
|
120
120
|
const original = await import("../../../README.md?raw");
|
|
121
121
|
const d = distance(markdown, original.default);
|
|
122
122
|
expect(d).lte(200);
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,10 @@ import { htmlToMarkdown } from "./html-to-markdown.js";
|
|
|
3
3
|
import { mdastSplitter } from "./md-splitter.js";
|
|
4
4
|
import { htmlToMdast } from "./html-to-mdast.js";
|
|
5
5
|
import { mdastToMarkdown } from "./mdast-to-markdown.js";
|
|
6
|
+
import { PRESET_EXTRACT_HAST, DEFAULT_EXTRACT_HAST } from "./extract-hast/index.js";
|
|
6
7
|
export {
|
|
8
|
+
DEFAULT_EXTRACT_HAST,
|
|
9
|
+
PRESET_EXTRACT_HAST,
|
|
7
10
|
htmlToMarkdown,
|
|
8
11
|
htmlToMdast,
|
|
9
12
|
mdastSplitter,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../../src/bin.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,2 @@
|
|
|
1
1
|
import type { Nodes as Hast } from "hast";
|
|
2
|
-
type ProxiedHast = Hast & {
|
|
3
|
-
parent: ProxiedHast | null;
|
|
4
|
-
};
|
|
5
|
-
declare module "hast" {
|
|
6
|
-
interface Element {
|
|
7
|
-
parent: ProxiedHast | null;
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
2
|
export declare const readabilityExtractHast: (hast: Hast) => Hast;
|
|
11
|
-
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readability.js","sourceRoot":"","sources":["../../../src/extract-hast/readability.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"readability.js","sourceRoot":"","sources":["../../../src/extract-hast/readability.ts"],"names":[],"mappings":"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"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,3 +2,4 @@ export { htmlToMarkdown, type HtmlToMarkdownOptions } from "./html-to-markdown";
|
|
|
2
2
|
export { mdastSplitter } from "./md-splitter";
|
|
3
3
|
export { htmlToMdast, type HtmlToMdastOptions } from "./html-to-mdast";
|
|
4
4
|
export { mdastToMarkdown } from "./mdast-to-markdown";
|
|
5
|
+
export { PRESET_EXTRACT_HAST, DEFAULT_EXTRACT_HAST } from "./extract-hast/index";
|
package/dist/types/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,OAAO,EAAE,cAAc,EAA8B,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,WAAW,EAA2B,MAAM,iBAAiB,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,OAAO,EAAE,cAAc,EAA8B,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,WAAW,EAA2B,MAAM,iBAAiB,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function logError(error: Error): void;
|
|
2
|
+
export declare function isUrl(str: string): boolean;
|
|
3
|
+
export declare function getNextAvailableFilePath(filePath: string): string;
|
|
4
|
+
export declare function changeFileExtension(filePath: string, newExtension: string): string;
|
|
5
|
+
export declare function urlToFilename(url: string): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin-utils.js","sourceRoot":"","sources":["../../../src/utils/bin-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// src/utils/bin-utils.ts
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { log } from "@clack/prompts";
|
|
5
|
+
function logError(error) {
|
|
6
|
+
log.error("An error occurred during processing");
|
|
7
|
+
console.error(error.message);
|
|
8
|
+
}
|
|
9
|
+
function isUrl(str) {
|
|
10
|
+
try {
|
|
11
|
+
new URL(str);
|
|
12
|
+
return true;
|
|
13
|
+
} catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function getNextAvailableFilePath(filePath) {
|
|
18
|
+
const parsedPath = path.parse(filePath);
|
|
19
|
+
const directory = parsedPath.dir;
|
|
20
|
+
const fullName = parsedPath.base;
|
|
21
|
+
const [firstPart, ...restParts] = fullName.split(".");
|
|
22
|
+
const restName = restParts.length > 0 ? `.${restParts.join(".")}` : "";
|
|
23
|
+
const baseName = firstPart.replace(/_\d+$/, "");
|
|
24
|
+
let counter = 1;
|
|
25
|
+
let nextFilePath = filePath;
|
|
26
|
+
while (fs.existsSync(nextFilePath)) {
|
|
27
|
+
const match = firstPart.match(/_(\d+)$/);
|
|
28
|
+
if (match) {
|
|
29
|
+
counter = Number.parseInt(match[1], 10) + 1;
|
|
30
|
+
}
|
|
31
|
+
const newName = `${baseName}_${counter}${restName}`;
|
|
32
|
+
nextFilePath = path.join(directory, newName);
|
|
33
|
+
counter++;
|
|
34
|
+
}
|
|
35
|
+
return nextFilePath;
|
|
36
|
+
}
|
|
37
|
+
function changeFileExtension(filePath, newExtension) {
|
|
38
|
+
const parsedPath = filePath.split("/");
|
|
39
|
+
const fileName = parsedPath[parsedPath.length - 1];
|
|
40
|
+
const formattedNewExtension = newExtension.startsWith(".") ? newExtension : `.${newExtension}`;
|
|
41
|
+
if (fileName.startsWith(".")) {
|
|
42
|
+
const parts = fileName.split(".");
|
|
43
|
+
if (parts.length === 2) {
|
|
44
|
+
return parsedPath.slice(0, -1).concat(`${fileName}${formattedNewExtension}`).join("/");
|
|
45
|
+
}
|
|
46
|
+
parts[parts.length - 1] = newExtension.replace(/^\./, "");
|
|
47
|
+
return parsedPath.slice(0, -1).concat(parts.join(".")).join("/");
|
|
48
|
+
}
|
|
49
|
+
const lastDotIndex = fileName.lastIndexOf(".");
|
|
50
|
+
const baseName = lastDotIndex !== -1 ? fileName.slice(0, lastDotIndex) : fileName;
|
|
51
|
+
const newFileName = `${baseName}${formattedNewExtension}`;
|
|
52
|
+
parsedPath[parsedPath.length - 1] = newFileName;
|
|
53
|
+
return parsedPath.join("/");
|
|
54
|
+
}
|
|
55
|
+
function urlToFilename(url) {
|
|
56
|
+
try {
|
|
57
|
+
const urlObj = new URL(url);
|
|
58
|
+
const domainParts = urlObj.hostname.split(".").reverse().reduce((acc, part, index) => {
|
|
59
|
+
if (index === 0) {
|
|
60
|
+
return acc;
|
|
61
|
+
}
|
|
62
|
+
if (acc.length >= 2) {
|
|
63
|
+
return acc;
|
|
64
|
+
}
|
|
65
|
+
if (part === "www") {
|
|
66
|
+
return acc;
|
|
67
|
+
}
|
|
68
|
+
return [part, ...acc];
|
|
69
|
+
}, []);
|
|
70
|
+
const domainString = domainParts.reverse().join("-");
|
|
71
|
+
const pathParts = urlObj.pathname.split("/").filter(Boolean);
|
|
72
|
+
const relevantPathParts = pathParts.slice(-2);
|
|
73
|
+
const pathString = relevantPathParts.map((part) => decodeURIComponent(part)).join("-");
|
|
74
|
+
let filename = [domainString, pathString].filter(Boolean).join("-");
|
|
75
|
+
filename = filename.toLowerCase().replace(/[<>:"/\\|?*\x00-\x1F]/g, "").replace(/[\s.]+/g, "-").replace(/^-+|-+$/g, "");
|
|
76
|
+
return filename || "output";
|
|
77
|
+
} catch {
|
|
78
|
+
return "output";
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export {
|
|
82
|
+
changeFileExtension,
|
|
83
|
+
getNextAvailableFilePath,
|
|
84
|
+
isUrl,
|
|
85
|
+
logError,
|
|
86
|
+
urlToFilename
|
|
87
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webforai",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "A library that provides a web interface for AI",
|
|
5
5
|
"author": "inaridiy",
|
|
6
6
|
"license": "MIT",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"type": "module",
|
|
27
27
|
"module": "dist/index.js",
|
|
28
28
|
"types": "dist/types/index.d.ts",
|
|
29
|
+
"bin": "dist/bin.js",
|
|
29
30
|
"exports": {
|
|
30
31
|
".": {
|
|
31
32
|
"types": "./dist/types/index.d.ts",
|
|
@@ -94,6 +95,8 @@
|
|
|
94
95
|
}
|
|
95
96
|
},
|
|
96
97
|
"dependencies": {
|
|
98
|
+
"@clack/prompts": "^0.7.0",
|
|
99
|
+
"commander": "^12.1.0",
|
|
97
100
|
"fastest-levenshtein": "^1.0.16",
|
|
98
101
|
"hast-util-from-html": "^2.0.1",
|
|
99
102
|
"hast-util-select": "^6.0.1",
|
|
@@ -105,13 +108,10 @@
|
|
|
105
108
|
"mdast-util-gfm": "^3.0.0",
|
|
106
109
|
"mdast-util-math": "^3.0.0",
|
|
107
110
|
"mdast-util-to-markdown": "^2.1.0",
|
|
111
|
+
"picocolors": "^1.0.1",
|
|
108
112
|
"puppeteer": "^22.10.0",
|
|
109
113
|
"trim-trailing-lines": "^2.1.0",
|
|
110
|
-
"unist-util-filter": "^5.0.1"
|
|
111
|
-
"unist-util-parents": "^3.0.0",
|
|
112
|
-
"unist-util-remove": "^4.0.0",
|
|
113
|
-
"unist-util-visit": "^5.0.0",
|
|
114
|
-
"unist-util-visit-parents": "^6.0.1"
|
|
114
|
+
"unist-util-filter": "^5.0.1"
|
|
115
115
|
},
|
|
116
116
|
"devDependencies": {
|
|
117
117
|
"@cloudflare/puppeteer": "^0.0.6",
|
|
@@ -132,7 +132,7 @@
|
|
|
132
132
|
"scripts": {
|
|
133
133
|
"copy:package.cjs.json": "pnpm ncp ./package.cjs.json ./dist/cjs/package.json && pnpm ncp ./package.cjs.json ./dist/types/package.json ",
|
|
134
134
|
"clean": "rimraf dist",
|
|
135
|
-
"build": "pnpm clean && tsx
|
|
135
|
+
"build": "pnpm clean && tsx build.ts && pnpm copy:package.cjs.json",
|
|
136
136
|
"test": "echo \"Error: no test specified\"",
|
|
137
137
|
"prerelease": "pnpm build",
|
|
138
138
|
"release": "np"
|