This commit is contained in:
2025-05-12 05:38:44 +09:00
parent dced21c3f8
commit 6d78bfa46e
8120 changed files with 1161564 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
/// <reference types="node" resolution-mode="require"/>
import { Writable } from 'node:stream';
import { Parser, type ParserOptions, type TreeAdapterTypeMap, type DefaultTreeAdapterMap } from 'parse5';
/**
* Streaming HTML parser with scripting support.
* A [writable stream](https://nodejs.org/api/stream.html#stream_class_stream_writable).
*
* @example
*
* ```js
* const ParserStream = require('parse5-parser-stream');
* const http = require('http');
* const { finished } = require('node:stream');
*
* // Fetch the page content and obtain it's <head> node
* http.get('http://inikulin.github.io/parse5/', res => {
* const parser = new ParserStream();
*
* finished(parser, () => {
* console.log(parser.document.childNodes[1].childNodes[0].tagName); //> 'head'
* });
*
* res.pipe(parser);
* });
* ```
*
*/
export declare class ParserStream<T extends TreeAdapterTypeMap = DefaultTreeAdapterMap> extends Writable {
parser: Parser<T>;
static getFragmentStream<T extends TreeAdapterTypeMap>(fragmentContext?: T['parentNode'] | null, options?: ParserOptions<T>): ParserStream<T>;
private lastChunkWritten;
private writeCallback;
private pendingHtmlInsertions;
/** The resulting document node. */
get document(): T['document'];
getFragment(): T['documentFragment'];
/**
* @param options Parsing options.
*/
constructor(options?: ParserOptions<T>, parser?: Parser<T>);
_write(chunk: string, _encoding: string, callback: () => void): void;
end(chunk?: any, encoding?: any, callback?: any): any;
}
export interface ParserStream<T extends TreeAdapterTypeMap = DefaultTreeAdapterMap> {
/**
* Raised when parser encounters a `<script>` element. If this event has listeners, parsing will be suspended once
* it is emitted. So, if `<script>` has the `src` attribute, you can fetch it, execute and then resume parsing just
* like browsers do.
*
* @example
*
* ```js
* const ParserStream = require('parse5-parser-stream');
* const http = require('http');
*
* const parser = new ParserStream();
*
* parser.on('script', (scriptElement, documentWrite, resume) => {
* const src = scriptElement.attrs.find(({ name }) => name === 'src').value;
*
* http.get(src, res => {
* // Fetch the script content, execute it with DOM built around `parser.document` and
* // `document.write` implemented using `documentWrite`.
* ...
* // Then resume parsing.
* resume();
* });
* });
*
* parser.end('<script src="example.com/script.js"></script>');
* ```
*
* @param event Name of the event
* @param handler
*/
on(event: 'script', handler: (scriptElement: T['element'], documentWrite: (html: string) => void, resume: () => void) => void): void;
/**
* Base event handler.
*
* @param event Name of the event
* @param handler Event handler
*/
on(event: string, handler: (...args: any[]) => void): this;
}
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1,90 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ParserStream = void 0;
const node_stream_1 = require("node:stream");
const parse5_1 = require("parse5");
/* eslint-disable unicorn/consistent-function-scoping -- The rule seems to be broken here. */
/**
* Streaming HTML parser with scripting support.
* A [writable stream](https://nodejs.org/api/stream.html#stream_class_stream_writable).
*
* @example
*
* ```js
* const ParserStream = require('parse5-parser-stream');
* const http = require('http');
* const { finished } = require('node:stream');
*
* // Fetch the page content and obtain it's <head> node
* http.get('http://inikulin.github.io/parse5/', res => {
* const parser = new ParserStream();
*
* finished(parser, () => {
* console.log(parser.document.childNodes[1].childNodes[0].tagName); //> 'head'
* });
*
* res.pipe(parser);
* });
* ```
*
*/
class ParserStream extends node_stream_1.Writable {
static getFragmentStream(fragmentContext, options) {
const parser = parse5_1.Parser.getFragmentParser(fragmentContext, options);
const stream = new ParserStream(options, parser);
return stream;
}
/** The resulting document node. */
get document() {
return this.parser.document;
}
getFragment() {
return this.parser.getFragment();
}
/**
* @param options Parsing options.
*/
constructor(options, parser = new parse5_1.Parser(options)) {
super({ decodeStrings: false });
this.parser = parser;
this.lastChunkWritten = false;
this.writeCallback = undefined;
this.pendingHtmlInsertions = [];
const resume = () => {
for (let i = this.pendingHtmlInsertions.length - 1; i >= 0; i--) {
this.parser.tokenizer.insertHtmlAtCurrentPos(this.pendingHtmlInsertions[i]);
}
this.pendingHtmlInsertions.length = 0;
//NOTE: keep parsing if we don't wait for the next input chunk
this.parser.tokenizer.resume(this.writeCallback);
};
const documentWrite = (html) => {
if (!this.parser.stopped) {
this.pendingHtmlInsertions.push(html);
}
};
const scriptHandler = (scriptElement) => {
if (this.listenerCount('script') > 0) {
this.parser.tokenizer.pause();
this.emit('script', scriptElement, documentWrite, resume);
}
};
this.parser.scriptHandler = scriptHandler;
}
//WritableStream implementation
_write(chunk, _encoding, callback) {
if (typeof chunk !== 'string') {
throw new TypeError('Parser can work only with string streams.');
}
this.writeCallback = callback;
this.parser.tokenizer.write(chunk, this.lastChunkWritten, this.writeCallback);
}
// TODO [engine:node@>=16]: Due to issues with Node < 16, we are overriding `end` instead of `_final`.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
end(chunk, encoding, callback) {
this.lastChunkWritten = true;
super.end(chunk || '', encoding, callback);
}
}
exports.ParserStream = ParserStream;
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"type":"commonjs"}

85
book/node_modules/parse5-parser-stream/dist/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,85 @@
/// <reference types="node" resolution-mode="require"/>
import { Writable } from 'node:stream';
import { Parser, type ParserOptions, type TreeAdapterTypeMap, type DefaultTreeAdapterMap } from 'parse5';
/**
* Streaming HTML parser with scripting support.
* A [writable stream](https://nodejs.org/api/stream.html#stream_class_stream_writable).
*
* @example
*
* ```js
* const ParserStream = require('parse5-parser-stream');
* const http = require('http');
* const { finished } = require('node:stream');
*
* // Fetch the page content and obtain it's <head> node
* http.get('http://inikulin.github.io/parse5/', res => {
* const parser = new ParserStream();
*
* finished(parser, () => {
* console.log(parser.document.childNodes[1].childNodes[0].tagName); //> 'head'
* });
*
* res.pipe(parser);
* });
* ```
*
*/
export declare class ParserStream<T extends TreeAdapterTypeMap = DefaultTreeAdapterMap> extends Writable {
parser: Parser<T>;
static getFragmentStream<T extends TreeAdapterTypeMap>(fragmentContext?: T['parentNode'] | null, options?: ParserOptions<T>): ParserStream<T>;
private lastChunkWritten;
private writeCallback;
private pendingHtmlInsertions;
/** The resulting document node. */
get document(): T['document'];
getFragment(): T['documentFragment'];
/**
* @param options Parsing options.
*/
constructor(options?: ParserOptions<T>, parser?: Parser<T>);
_write(chunk: string, _encoding: string, callback: () => void): void;
end(chunk?: any, encoding?: any, callback?: any): any;
}
export interface ParserStream<T extends TreeAdapterTypeMap = DefaultTreeAdapterMap> {
/**
* Raised when parser encounters a `<script>` element. If this event has listeners, parsing will be suspended once
* it is emitted. So, if `<script>` has the `src` attribute, you can fetch it, execute and then resume parsing just
* like browsers do.
*
* @example
*
* ```js
* const ParserStream = require('parse5-parser-stream');
* const http = require('http');
*
* const parser = new ParserStream();
*
* parser.on('script', (scriptElement, documentWrite, resume) => {
* const src = scriptElement.attrs.find(({ name }) => name === 'src').value;
*
* http.get(src, res => {
* // Fetch the script content, execute it with DOM built around `parser.document` and
* // `document.write` implemented using `documentWrite`.
* ...
* // Then resume parsing.
* resume();
* });
* });
*
* parser.end('<script src="example.com/script.js"></script>');
* ```
*
* @param event Name of the event
* @param handler
*/
on(event: 'script', handler: (scriptElement: T['element'], documentWrite: (html: string) => void, resume: () => void) => void): void;
/**
* Base event handler.
*
* @param event Name of the event
* @param handler Event handler
*/
on(event: string, handler: (...args: any[]) => void): this;
}
//# sourceMappingURL=index.d.ts.map

86
book/node_modules/parse5-parser-stream/dist/index.js generated vendored Normal file
View File

@@ -0,0 +1,86 @@
import { Writable } from 'node:stream';
import { Parser } from 'parse5';
/* eslint-disable unicorn/consistent-function-scoping -- The rule seems to be broken here. */
/**
* Streaming HTML parser with scripting support.
* A [writable stream](https://nodejs.org/api/stream.html#stream_class_stream_writable).
*
* @example
*
* ```js
* const ParserStream = require('parse5-parser-stream');
* const http = require('http');
* const { finished } = require('node:stream');
*
* // Fetch the page content and obtain it's <head> node
* http.get('http://inikulin.github.io/parse5/', res => {
* const parser = new ParserStream();
*
* finished(parser, () => {
* console.log(parser.document.childNodes[1].childNodes[0].tagName); //> 'head'
* });
*
* res.pipe(parser);
* });
* ```
*
*/
export class ParserStream extends Writable {
static getFragmentStream(fragmentContext, options) {
const parser = Parser.getFragmentParser(fragmentContext, options);
const stream = new ParserStream(options, parser);
return stream;
}
/** The resulting document node. */
get document() {
return this.parser.document;
}
getFragment() {
return this.parser.getFragment();
}
/**
* @param options Parsing options.
*/
constructor(options, parser = new Parser(options)) {
super({ decodeStrings: false });
this.parser = parser;
this.lastChunkWritten = false;
this.writeCallback = undefined;
this.pendingHtmlInsertions = [];
const resume = () => {
for (let i = this.pendingHtmlInsertions.length - 1; i >= 0; i--) {
this.parser.tokenizer.insertHtmlAtCurrentPos(this.pendingHtmlInsertions[i]);
}
this.pendingHtmlInsertions.length = 0;
//NOTE: keep parsing if we don't wait for the next input chunk
this.parser.tokenizer.resume(this.writeCallback);
};
const documentWrite = (html) => {
if (!this.parser.stopped) {
this.pendingHtmlInsertions.push(html);
}
};
const scriptHandler = (scriptElement) => {
if (this.listenerCount('script') > 0) {
this.parser.tokenizer.pause();
this.emit('script', scriptElement, documentWrite, resume);
}
};
this.parser.scriptHandler = scriptHandler;
}
//WritableStream implementation
_write(chunk, _encoding, callback) {
if (typeof chunk !== 'string') {
throw new TypeError('Parser can work only with string streams.');
}
this.writeCallback = callback;
this.parser.tokenizer.write(chunk, this.lastChunkWritten, this.writeCallback);
}
// TODO [engine:node@>=16]: Due to issues with Node < 16, we are overriding `end` instead of `_final`.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
end(chunk, encoding, callback) {
this.lastChunkWritten = true;
super.end(chunk || '', encoding, callback);
}
}
//# sourceMappingURL=index.js.map