UNPKG

docutils-ts

Version:

Port of the Python Docutils library to TypeScript

255 lines (226 loc) 10.5 kB
import { StringInput, StringOutput } from './io.js'; import { Publisher } from './publisher.js'; import { defaultPublisherOptions, defaultUsage, defaultDescription } from './constants.js'; import { NoOpLogger } from './noOpLogger.js'; export { Publisher }; // Default implementation that warns about missing implementation const defaultFileSystem = { async writeFile(path, data, options) { console.warn('fileSystem.writeFile is not implemented in this environment.'); }, async readFile(path, options) { console.warn('fileSystem.readFile is not implemented in this environment.'); return ''; } }; // Singleton instance that can be replaced let _fileSystemInstance = defaultFileSystem; // Public API export const fileSystem = { // Method implementations that delegate to the current instance writeFile: (path, data, options) => _fileSystemInstance.writeFile(path, data), readFile: (path, options) => _fileSystemInstance.readFile(path), // Method to configure a custom implementation setImplementation: (implementation) => { _fileSystemInstance = implementation; }, // Method to reset to default implementation resetToDefault: () => { _fileSystemInstance = defaultFileSystem; } }; export function publish(args) { const myArgs = { ...defaultPublisherOptions, ...args }; const { reader, readerName, parser, parserName, writer, writerName, settings, } = myArgs; const pub = new Publisher({ reader, parser, writer, settings, logger: myArgs.logger, }); pub.setComponents(readerName, parserName, writerName); } /** * Set up & run a `Publisher` for command-line-based file I/O (input and * output file paths taken automatically from the command line). Return the * encoded string output also. * * Parameters: see `publish_programmatically` for the remainder. * * - `argv`: Command-line argument list to use instead of ``sys.argv[1:]``. * - `usage`: Usage string, output if there's a problem parsing the command * line. * - `description`: Program description, output for the "--help" option * (along with command-line option descriptions). * */ export async function publishCmdLine(args) { checkNodeVersion(); const _defaults = { readerName: 'standalone', parserName: 'restructuredtext', usage: defaultUsage, description: defaultDescription, enableExitStatus: true, }; args = { ..._defaults, ...args }; if (args.logger === undefined) { args.logger = new NoOpLogger(); } args.logger.silly('publishCmdLine'); const { reader, readerName, parser, parserName, writer, writerName, settings, settingsSpec, settingsOverrides, configSection, enableExitStatus, argv, usage, description, } = args; const pub = new Publisher({ reader, parser, writer, settings, logger: args.logger, }); pub.setComponents(readerName, parserName, writerName); const output = pub.publish({ argv, usage, description, settingsSpec, settingsOverrides, configSection, enableExitStatus }); return output; } // export function publish_string(options: any): string { // const input = options?.source || ""; // return `[docutils-ts] received: ${input.slice(0, 60)}...`; // } /* * Set up & run a `Publisher` for programmatic use with string I/O. * * Accepts a `bytes` or `str` instance as `source`. * * The output is encoded according to the `output_encoding`_ setting; * the return value is a `bytes` instance (unless `output_encoding`_ is * "unicode", cf. `docutils.io.StringOutput.write()`). * * Parameters: see `publish_programmatically()` or * https://docutils.sourceforge.io/docs/api/publisher.html#publish-string * * This function is provisional because in Python 3 name and behaviour * no longer match. * * .. _output_encoding: * https://docutils.sourceforge.io/docs/user/config.html#output-encoding */ export async function publish_string(options) { checkNodeVersion(); // The "*_name" arguments are deprecated. _name_arg_warning(options.readerName, options.parserName, options.writerName); // The default is set in publish_programmatically(). const [output, _publisher] = await publish_programmatically({ sourceClass: StringInput, destinationClass: StringOutput, ...options }); return output; } function _name_arg_warning(...name_args) { const components = ['reader', 'parser', 'writer']; for (let i = 0; i < components.length; i++) { const component = components[i]; const name_arg = name_args[i]; if (name_arg !== null && name_arg !== undefined) { console.warn(`Argument "${component}_name" will be removed in ` + `Docutils 2.0. Specify ${component} name ` + `in the "${component}" argument.`); } } } /** * Set up & run a `Publisher` for custom programmatic use. Return the output (as `str` or `bytes`, depending on `destination_class`, writer, and the "output_encoding" setting) and the Publisher object. Internal: Applications should not call this function directly. If it does seem to be necessary to call this function directly, please write to the Docutils-develop mailing list <https://docutils.sourceforge.io/docs/user/mailing-lists.html#docutils-develop>. Parameters: * `source_class` **required**: The class for dynamically created source objects. Typically `io.FileInput` or `io.StringInput`. * `source`: Type depends on `source_class`: - If `source_class` is `io.FileInput`: Either a file-like object (must have 'read' and 'close' methods), or ``None`` (`source_path` is opened). If neither `source` nor `source_path` are supplied, `sys.stdin` is used. - If `source_class` is `io.StringInput` **required**: The input as either a `bytes` object (ensure the 'input_encoding' setting matches its encoding) or a `str` object. * `source_path`: Type depends on `source_class`: - `io.FileInput`: Path to the input file, opened if no `source` supplied. - `io.StringInput`: Optional. Path to the file or name of the object that produced `source`. Only used for diagnostic output. * `destination_class` **required**: The class for dynamically created destination objects. Typically `io.FileOutput` or `io.StringOutput`. * `destination`: Type depends on `destination_class`: - `io.FileOutput`: Either a file-like object (must have 'write' and 'close' methods), or ``None`` (`destination_path` is opened). If neither `destination` nor `destination_path` are supplied, `sys.stdout` is used. - `io.StringOutput`: Not used; pass ``None``. * `destination_path`: Type depends on `destination_class`: - `io.FileOutput`: Path to the output file. Opened if no `destination` supplied. - `io.StringOutput`: Path to the file or object which will receive the output; optional. Used for determining relative paths (stylesheets, source links, etc.). * `reader`: A `docutils.readers.Reader` instance, name, or alias. Default: "standalone". * `reader_name`: Deprecated. Use `reader`. * `parser`: A `docutils.parsers.Parser` instance, name, or alias. Default: "restructuredtext". * `parser_name`: Deprecated. Use `parser`. * `writer`: A `docutils.writer.Writer` instance, name, or alias. Default: "pseudoxml". * `writer_name`: Deprecated. Use `writer`. * `settings`: A runtime settings (`docutils.frontend.Values`) object, for dotted-attribute access to runtime settings. It's the end result of the `SettingsSpec`, config file, and option processing. If `settings` is passed, it's assumed to be complete and no further setting/config/option processing is done. * `settings_spec`: A `docutils.SettingsSpec` subclass or object. Provides extra application-specific settings definitions independently of components. In other words, the application becomes a component, and its settings data is processed along with that of the other components. Used only if no `settings` specified. * `settings_overrides`: A dictionary containing application-specific settings defaults that override the defaults of other components. Used only if no `settings` specified. * `config_section`: A string, the name of the configuration file section for this application. Overrides the ``config_section`` attribute defined by `settings_spec`. Used only if no `settings` specified. * `enable_exit_status`: Boolean; enable exit status at end of processing? */ async function publish_programmatically(options) { checkNodeVersion(); if (options.reader === undefined && !options.readerName) { options.readerName = 'standalone'; } if (options.parser === undefined && !options.parserName) { options.parserName = 'restructuredtext'; } if (options.writer === undefined && !options.writerName) { options.writerName = 'pseudoxml'; } // TODO : Get better logger! const publisher = new Publisher({ reader: options.reader, parser: options.parser, writer: options.writer, settings: options.settings, sourceClass: options.sourceClass, destinationClass: options.destinationClass, logger: new NoOpLogger() }); publisher.setComponents(options.readerName, options.parserName, options.writerName); publisher.process_programmatic_settings(options.settingsSpec, options.settingsOverrides, options.configSection); publisher.setSource({ source: options.source, sourcePath: options.sourcePath }); publisher.setDestination({ destination: options.destination, destinationPath: options.destinationPath }); const output = await publisher.publish({ enable_exit_status: options.enableExitStatus }); return [output, publisher]; } function checkNodeVersion() { if (typeof process !== 'undefined' && process.versions?.node) { if (typeof String.prototype.replaceAll !== 'function') { console.error('❌ Your Node.js version does not support String.prototype.replaceAll.'); console.error('Please upgrade to Node.js v15+.'); process.exit(1); } } }