From a8ef16e8c447ba6dac04020568e79f1f7bc626bb Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Tue, 26 Mar 2024 15:40:02 -0400 Subject: [PATCH 1/3] Added documentation --- src/internal/core/index.ts | 134 ++++++++++++++++++++ src/internal/index.ts | 18 +++ src/internal/parser.ts | 253 +++++++++++++++++++++++++++++++++++++ 3 files changed, 405 insertions(+) diff --git a/src/internal/core/index.ts b/src/internal/core/index.ts index 0ee19f4..89e23df 100644 --- a/src/internal/core/index.ts +++ b/src/internal/core/index.ts @@ -2,18 +2,37 @@ // Parsimmon-like stateful parser combinators // +/** + * Holds the information from a successful parse. + */ export type Success = { success: true; value: T; index: number; }; +/** + * Represents a failed parse. + */ export type Failure = { success: false }; +/** + * Possible results from a parse. + */ export type Result = Success | Failure; +/** + * The function used by a parser to determine if it succeeds or fails. + */ export type ParserHandler = (input: string, index: number, state: any) => Result +/** + * A function that always returns a parse success. + * + * @param index The index of the success. + * @param value The value of the success. + * @returns A {@link Success} object. + */ export function success(index: number, value: T): Success { return { success: true, @@ -22,10 +41,18 @@ export function success(index: number, value: T): Success { }; } +/** + * A function that always returns a parse failure. + * + * @returns A {@link Failure} object. + */ export function failure(): Failure { return { success: false }; } +/** + * The parser class. + */ export class Parser { public name?: string; public handler: ParserHandler; @@ -50,6 +77,13 @@ export class Parser { this.name = name; } + /** + * A function that maps the result of the parse with the provided function if successful, and returns a {@link Failure} + * otherwise. + * + * @param fn The function used to map the output of the parser. + * @returns The result of the parser mapped with `fn`. + */ map(fn: (value: T) => U): Parser { return new Parser((input, index, state) => { const result = this.handler(input, index, state); @@ -60,6 +94,11 @@ export class Parser { }); } + /** + * A function that returns the plaintext related to the {@link Success} and a {@link Failure} otherwise. + * + * @returns The plaintext related to the successful parse, and a {@link Failure} if the parse failed. + */ text(): Parser { return new Parser((input, index, state) => { const result = this.handler(input, index, state); @@ -71,6 +110,13 @@ export class Parser { }); } + /** + * A function that returns a {@link Parser} that must succeed at least of `min` times in order to return + * a {@link Success} and returns a {@link Failure} otherwise. + * + * @param min The minimum amount of times this parse must succeed to return a {@link Success}. + * @returns A Parser that returns a {@link Success} object it matches enough times, and a {@link Failure} otherwise. + */ many(min: number): Parser { return new Parser((input, index, state) => { let result; @@ -91,6 +137,13 @@ export class Parser { }); } + /** + * A function that checks if the supplied separator appears between this separator's value. + * + * @param separator The parser representing the separator that must appear between this parser's value. + * @param min The minimum amount of times the separator must appear. + * @returns A {@link Success} object if the minimum separator count is met, and a {@link Failure} otherwise. + */ sep(separator: Parser, min: number): Parser { if (min < 1) { throw new Error('"min" must be a value greater than or equal to 1.'); @@ -104,6 +157,12 @@ export class Parser { ]).map(result => [result[0], ...result[1]]); } + /** + * A function that attempts to match this parser, but returns a {@link Success} object with the + * value `null` if it fails. + * + * @returns A {@link Success} object. + */ option(): Parser { return alt([ this, @@ -112,6 +171,12 @@ export class Parser { } } +/** + * A function that returns a {@link Parser} that succeeds if it matches the supplied string. + * + * @param value The string that the returned {@link Parser} checks for. + * @returns A {@link Parser} that matches the supplied string. + */ export function str(value: T): Parser { return new Parser((input, index, _state) => { if ((input.length - index) < value.length) { @@ -124,6 +189,12 @@ export function str(value: T): Parser { }); } +/** + * A function that returns {@link Parser} that succeeds if the input matches the supplied regular expression. + * + * @param pattern The regular expression that the returned {@link Parser} tries to match. + * @returns A {@link Parser} that checks if the input matches the supplied regular expression. + */ export function regexp(pattern: T): Parser { const re = RegExp(`^(?:${pattern.source})`, pattern.flags); return new Parser((input, index, _state) => { @@ -136,6 +207,20 @@ export function regexp(pattern: T): Parser { }); } +/** + * A function that returns a {@link Parser} that goes through the parsers provided, in order, and checks that they all + * succeed. A {@link Failure} object is returned if any of the parsers fails. + * The value in the {@link Success} returned by the parser varies depending on the value of `select`: + * + * If select is `null`, then the array of the results of the supplied parsers is returned, otherwise the value + * in the array at the specified index is returned. + * + * @param parsers The array of {@link Parser Parsers} that are checked to see if it succeeds. + * @param select The index of the result array that is returned. + * @returns A {@link Parser} that runs through the parsers in the order that they were provided and returns + * a value based on the state of `select` (the entire array if `null`, else the value held at the + * index specified by `select`). + */ export function seq(parsers: Parser[], select?: number): Parser { return new Parser((input, index, state) => { let result; @@ -153,6 +238,15 @@ export function seq(parsers: Parser[], select?: number): Parser { }); } +/** + * A function that returns a {@link Parser} that goes through the parsers provided, in order, and checks if each succeeds. + * If one fails, the next parser is tested, and this pattern is continued until the final parser is tested, at which point + * the parser will return a {@link Failure} if it still fails. If any of the parsers succeed, the resulting {@link Success} + * is returned immediately. + * + * @param parsers The {@link Parser Parsers} that should be used. + * @returns A {@link Parser} that returns the first {@link Success} from the supplied parsers. + */ export function alt(parsers: Parser[]): Parser { return new Parser((input, index, state) => { let result; @@ -166,12 +260,24 @@ export function alt(parsers: Parser[]): Parser { }); } +/** + * A function that returns a {@link Parser} that always succeeds, returning a {@link Success} object with the supplied value. + * + * @param value The value to be used in the returned {@link Success} object. + * @returns A {@link Parser} that always returns a {@link Success} with the specified value. + */ function succeeded(value: T): Parser { return new Parser((_input, index, _state) => { return success(index, value); }); } +/** + * A function that returns a {@link Parser} that inverts the result of the parser supplied. + * + * @param parser The {@link Parser} to be matched. + * @returns A {@link Success} with the value `null` if the parser fails, or a {@link Failure} if it succeeds. + */ export function notMatch(parser: Parser): Parser { return new Parser((input, index, state) => { const result = parser.handler(input, index, state); @@ -181,6 +287,15 @@ export function notMatch(parser: Parser): Parser { }); } +/** + * A function that returns a {@link Parser} that fails if `parserExcluded` succeeds, and returns the result of `parserIncluded` + * otherwise. + * + * @param parserIncluded The {@link Parser} that should succeed + * @param parserExcluded The {@link Parser} that should fail + * @returns A {@link Failure} object if `parserExcluded` succeeds, or if `parserIncluded` fails, and a {@link Success} object + * otherwise. + */ export function difference(parserIncluded: Parser, parserExcluded: Parser): Parser { return new Parser((input, index, state) => { const exclude = parserExcluded.handler(input, index, state); @@ -193,11 +308,16 @@ export function difference(parserIncluded: Parser, parserExcluded: Parser { if ((input.length - index) < 1) { return failure(); @@ -206,6 +326,10 @@ export const char = new Parser((input, index, _state) => { return success(index + 1, value); }); +/** + * A {@link Parser} that checks that the current position is the beginning of a line. For this parser to succeed, + * either the current index must be zero, or the previous character is a `\n` or `\r`. + */ export const lineBegin = new Parser((input, index, state) => { if (index === 0) { return success(index, null); @@ -219,6 +343,10 @@ export const lineBegin = new Parser((input, index, state) => { return failure(); }); +/** + * A {@link Parser} that checks that the current position is the end of a line. For this parser to succeed, either the current + * index must be equal to the input length, or the current character is a `\n` or `\r`. + */ export const lineEnd = new Parser((input, index, state) => { if (index === input.length) { return success(index, null); @@ -232,6 +360,12 @@ export const lineEnd = new Parser((input, index, state) => { return failure(); }); +/** + * A function that lazily loads the supplied {@link Parser} + * + * @param fn The {@link Parser} that the returned parser should use. + * @returns A {@link Parser} that checks using the supplied parser's {@link Parser.handler} + */ export function lazy(fn: () => Parser): Parser { const parser: Parser = new Parser((input, index, state) => { parser.handler = fn().handler; diff --git a/src/internal/index.ts b/src/internal/index.ts index 45138c3..8ccd5b6 100644 --- a/src/internal/index.ts +++ b/src/internal/index.ts @@ -3,10 +3,21 @@ import { language } from './parser'; import { mergeText } from './util'; import * as P from './core'; +/** + * A type representing the available options for the full parser. + */ export type FullParserOpts = { nestLimit?: number; }; +/** + * A function that parses through the input plaintext with the full parser and returns the AST representing the + * result. + * + * @param input The input string to parse. + * @param opts The options used for the parsing. + * @returns An array of nodes representing the resulting styles. + */ export function fullParser(input: string, opts: FullParserOpts): M.MfmNode[] { const result = language.fullParser.handler(input, 0, { nestLimit: (opts.nestLimit != null) ? opts.nestLimit : 20, @@ -17,6 +28,13 @@ export function fullParser(input: string, opts: FullParserOpts): M.MfmNode[] { return mergeText(result.value); } +/** + * A function that parses through the input plaintext with the simple parser and returns the AST representing the + * result. + * + * @param input The input string to parse. + * @returns An array of simple nodes represennting the resulting styles. + */ export function simpleParser(input: string): M.MfmSimpleNode[] { const result = language.simpleParser.handler(input, 0, { }) as P.Success; return mergeText(result.value); diff --git a/src/internal/parser.ts b/src/internal/parser.ts index b2bf6b5..7ffffae 100644 --- a/src/internal/parser.ts +++ b/src/internal/parser.ts @@ -12,10 +12,25 @@ import twemojiRegex from '@twemoji/parser/dist/lib/regex'; type ArgPair = { k: string, v: string | true }; type Args = Record; +/** A {@link P.Parser Parser} that matches all whitespace characters other than ones representing new lines */ const space = P.difference(P.regexp(/\s/), P.newline); +/** A {@link P.Parser Parser} that matches all alphanumeric characters */ const alphaAndNum = P.regexp(/\p{Letter}|\p{Number}/iu); +/** A {@link P.Parser Parser} that matches any valid new line sequences */ const newLine = P.alt([P.crlf, P.cr, P.lf]); +/** + * A function that returns a {@link P.Parser Parser} which goes through the supplied parsers sequentially. + * If the first provided parser fails, a {@link P.Failure Failure} object is returned, the plaintext of the + * successfully parsed portion of the input if any other parsers fail, and an array of the values of the + * parsers' {@link P.Success Successes}. + * + * @param parsers The list of {@link P.Parser Parsers} to use. + * @returns A {@link P.Parser Parser} that goes through the supplied parsers sequentially and makes sure that each + * succeeds. If the first parser fails, a {@link P.Failure Failure} object is returned. If any other parser + * fails, the plaintext of the successfully parsed portion of the input text is returned. If all succeed, + * the array of each {@link P.Success Success'} value is returned. + */ function seqOrText(parsers: P.Parser[]): P.Parser { return new P.Parser((input, index, state) => { const accum: any[] = []; @@ -36,18 +51,34 @@ function seqOrText(parsers: P.Parser[]): P.Parser { }); } +/** + * A {@link P.Parser Parser} that succeeds if the supplied state is not a link label. + */ const notLinkLabel = new P.Parser((_input, index, state) => { return (!state.linkLabel) ? P.success(index, null) : P.failure(); }); +/** + * A {@link P.Parser Parser} that succeeds if the current nest depth is less than the nest limit. + */ const nestable = new P.Parser((_input, index, state) => { return (state.depth < state.nestLimit) ? P.success(index, null) : P.failure(); }); +/** + * A function that returns a {@link P.Parser Parser} that calls `parser` if it is possible to nest, and `fallback` + * otherwise. + * + * @param parser The {@link P.Parser Parser} that gets used if it is currently possible to nest. + * @param fallback The {@link P.Parser Parser} that gets used if it is not currently possible to nest. + * If `null`, {@link P.char} is used. + * @returns A {@link P.Parser Parser} that checks that it is possible to nest, returning the result of `parser` if it is, + * otherwise returning the result of `fallback` + */ function nest(parser: P.Parser, fallback?: P.Parser): P.Parser { // nesting limited? -> No: specified parser, Yes: fallback parser (default = P.char) const inner = P.alt([ @@ -62,15 +93,37 @@ function nest(parser: P.Parser, fallback?: P.Parser): P.Parser { return r.full.many(0); }, + /** + * A {@link P.Parser Parser} that matches {@link language.unicodeEmoji}, {@link language.emojiCode}, + * and {@link language.text} as many times as possible + * + * @param r The rules of SFM + * @returns A {@link P.Parser Parser} that matches very few SFM rules as many times as possible. + */ simpleParser: r => { return r.simple.many(0); }, + /** + * A {@link P.Parser Parser} that matches any SFM rule. + * + * @param r The rules of SFM + * @returns A {@link P.Parser Parser} that matches any rule. + */ full: r => { return P.alt([ // Regexp @@ -129,6 +182,13 @@ export const language = P.createLanguage({ ]); }, + /** + * A {@link P.Parser Parser} that only matches {@link language.unicodeEmoji}, {@link language.emojiCode}, + * and {@link language.text}. + * + * @param r The rules of SFM + * @returns A {@link P.Parser Parser} that matches very few SFM rules. + */ simple: r => { return P.alt([ r.unicodeEmoji, // Regexp @@ -137,6 +197,12 @@ export const language = P.createLanguage({ ]); }, + /** + * A {@link P.Parser Parser} that only matches rules that can be done without disrupting text. + * + * @param r The rules of SFM + * @returns A {@link P.Parser Parser} that matches all inline rules. + */ inline: r => { return P.alt([ // Regexp @@ -185,6 +251,12 @@ export const language = P.createLanguage({ ]); }, + /** + * A {@link P.Parser Parser} that matches single lines that begin with a `>` character. + * + * @param r The rules of SFM + * @returns The {@link P.Parser Parser} for this rule + */ quote: r => { const lines: P.Parser = P.seq([ P.str('>'), @@ -222,6 +294,14 @@ export const language = P.createLanguage({ }); }, + /** + * A {@link P.Parser Parser} that matches multi-line text that is surrounded by the ` ``` ` mark. + * Text directly after the opening mark decides the language that the syntax highlighting uses. + * The marks must be on their own lines. + * + * @param r The rules of SFM + * @returns The {@link P.Parser Parser} for this rule + */ codeBlock: r => { const mark = P.str('```'); return P.seq([ @@ -242,6 +322,13 @@ export const language = P.createLanguage({ }); }, + /** + * A {@link P.Parser Parser} that matches multi-line text that is opened with `\[` and closed with `\]`. + * The marks do not have to be on their own lines, nor do they need to be the first. + * + * @param r The rules of SFM + * @returns The {@link P.Parser Parser} for this rule + */ mathBlock: r => { const open = P.str('\\['); const close = P.str('\\]'); @@ -259,6 +346,14 @@ export const language = P.createLanguage({ }); }, + /** + * A {@link P.Parser Parser} that matches multi-line text that is opened with `
` and closed with `
`. + * The marks do not have to be on their own lines. + * The opening mark must appear at the beginning of its line, and the closing mark must appear at the end of its line. + * + * @param r The rules of SFM + * @returns The {@link P.Parser Parser} for this rule + */ centerTag: r => { const open = P.str('
'); const close = P.str('
'); @@ -277,6 +372,13 @@ export const language = P.createLanguage({ }); }, + /** + * A {@link P.Parser Parser} that matches multi-line text that is surrounded with the `***` mark. + * The marks do not have to be on their own lines and have no restrictions on placement. + * + * @param r The rules of SFM + * @returns The {@link P.Parser Parser} for this rule + */ big: r => { const mark = P.str('***'); return seqOrText([ @@ -289,6 +391,13 @@ export const language = P.createLanguage({ }); }, + /** + * A {@link P.Parser Parser} that matches multi-line text that is surrounded with the `**` mark. + * The marks do not have to be on their own lines and have no restrictions on placement. + * + * @param r The rules of SFM + * @returns The {@link P.Parser Parser} for this rule + */ boldAsta: r => { const mark = P.str('**'); return seqOrText([ @@ -301,6 +410,13 @@ export const language = P.createLanguage({ }); }, + /** + * A {@link P.Parser Parser} that matches multi-line text that is opened with `` and closed with ``. + * The marks do not have to be on their own lines and have no restrictions on placement. + * + * @param r The rules of SFM + * @returns The {@link P.Parser Parser} for this rule + */ boldTag: r => { const open = P.str(''); const close = P.str(''); @@ -314,6 +430,13 @@ export const language = P.createLanguage({ }); }, + /** + * A {@link P.Parser Parser} that matches multi-line text that is surrounded with the `__` mark. + * The marks do not have to be on their own lines and have no restrictions on placement. + * + * @param r The rules of SFM + * @returns The {@link P.Parser Parser} for this rule + */ boldUnder: r => { const mark = P.str('__'); return P.seq([ @@ -323,6 +446,13 @@ export const language = P.createLanguage({ ]).map(result => M.BOLD(mergeText(result[1] as string[]))); }, + /** + * A {@link P.Parser Parser} that matches multi-line text that is opened with `` and closed with ``. + * The marks do not have to be on their own lines and have no restrictions on placement. + * + * @param r The rules of SFM + * @returns The {@link P.Parser Parser} for this rule + */ smallTag: r => { const open = P.str(''); const close = P.str(''); @@ -336,6 +466,13 @@ export const language = P.createLanguage({ }); }, + /** + * A {@link P.Parser Parser} that matches multi-line text that is opened with `` and closed with ``. + * The marks do not have to be on their own lines and have no restrictions on placement. + * + * @param r The rules of SFM + * @returns The {@link P.Parser Parser} for this rule + */ italicTag: r => { const open = P.str(''); const close = P.str(''); @@ -349,6 +486,13 @@ export const language = P.createLanguage({ }); }, + /** + * A {@link P.Parser Parser} that matches multi-line text that is surrounded with the `*` mark. + * The marks do not have to be on their own lines and have no restrictions on placement. + * + * @param r The rules of SFM + * @returns The {@link P.Parser Parser} for this rule + */ italicAsta: r => { const mark = P.str('*'); const parser = P.seq([ @@ -370,6 +514,13 @@ export const language = P.createLanguage({ }); }, + /** + * A {@link P.Parser Parser} that matches multi-line text that is surrounded with the `_` mark. + * The marks do not have to be on their own lines and have no restrictions on placement. + * + * @param r The rules of SFM + * @returns The {@link P.Parser Parser} for this rule + */ italicUnder: r => { const mark = P.str('_'); const parser = P.seq([ @@ -391,6 +542,13 @@ export const language = P.createLanguage({ }); }, + /** + * A {@link P.Parser Parser} that matches multi-line text that is opened with `` and closed with ``. + * The marks do not have to be on their own lines and have no restrictions on placement. + * + * @param r The rules of SFM + * @returns The {@link P.Parser Parser} for this rule + */ strikeTag: r => { const open = P.str(''); const close = P.str(''); @@ -404,6 +562,13 @@ export const language = P.createLanguage({ }); }, + /** + * A {@link P.Parser Parser} that matches multi-line text that is surrounded with the `~~` mark. + * The marks do not have to be on their own lines and have no restrictions on placement. + * + * @param r The rules of SFM + * @returns The {@link P.Parser Parser} for this rule + */ strikeWave: r => { const mark = P.str('~~'); return seqOrText([ @@ -416,11 +581,24 @@ export const language = P.createLanguage({ }); }, + /** + * A {@link P.Parser Parser} that matches unicode emojis according to a regex. + * + * @param r The rules of SFM + * @returns The {@link P.Parser Parser} for this rule + */ unicodeEmoji: r => { const emoji = RegExp(twemojiRegex.source); return P.regexp(emoji).map(content => M.UNI_EMOJI(content)); }, + /** + * A {@link P.Parser Parser} that matches multi-line text that is opened with `` and closed with ``. + * The marks do not have to be on their own lines and have no restrictions on placement. + * + * @param r The rules of SFM + * @returns The {@link P.Parser Parser} for this rule + */ plainTag: r => { const open = P.str(''); const close = P.str(''); @@ -483,6 +661,13 @@ export const language = P.createLanguage({ }); }, + /** + * A {@link P.Parser Parser} that matches multi-line text that is surrounded with the `` ` `` mark. + * The marks do not have to be on their own lines and have no restrictions on placement. + * + * @param r The rules of SFM + * @returns The {@link P.Parser Parser} for this rule + */ inlineCode: r => { const mark = P.str('`'); return P.seq([ @@ -495,6 +680,13 @@ export const language = P.createLanguage({ ]).map(result => M.INLINE_CODE(result[1].join(''))); }, + /** + * A {@link P.Parser Parser} that matches single-line text opened with `\(` and closed with `\)`. + * The marks must be on the same line, but have no other restrictions on placement. + * + * @param r The rules of SFM + * @returns The {@link P.Parser Parser} for this rule + */ mathInline: r => { const open = P.str('\\('); const close = P.str('\\)'); @@ -508,6 +700,14 @@ export const language = P.createLanguage({ ]).map(result => M.MATH_INLINE(result[1].join(''))); }, + /** + * A {@link P.Parser Parser} that matches user mentions, which all must begin with `@{username}`, but only have to be followed by + * `@{hostname}` if the user is on a different instance. + * The mention must be contained within one line, but it has no other restrictions on placement. + * + * @param r the rules of SFM + * @returns The {@link P.Parser Parser} for this rule + */ mention: r => { const parser = P.seq([ notLinkLabel, @@ -574,6 +774,15 @@ export const language = P.createLanguage({ }); }, + /** + * A {@link P.Parser Parser} that matches single word hashtags starting with the character `#`. + * The contents of the hashtag are limited to alphanumeric characters, but cannot be made up of exclusively numbers. + * There are some characters that must be closed with another in order for the parse to succeed. + * There are no restrictions on the placement of hashtags. + * + * @param r The rules of SFM + * @returns A {@link P.Parser Parser} for this rule + */ hashtag: r => { const mark = P.str('#'); const hashTagChar = P.seq([ @@ -620,6 +829,14 @@ export const language = P.createLanguage({ }); }, + /** + * A {@link P.Parser Parser} that matches single word emojis surrounded by the `:` mark. + * The marks must be on the same line, and alphanumeric characters cannot appear both in front + * of, and behind, the opening and closing marks respectively. + * + * @param r The rules of SFM + * @returns A {@link P.Parser Parser} for this rule + */ emojiCode: r => { const side = P.notMatch(P.regexp(/[a-z0-9]/i)); const mark = P.str(':'); @@ -632,6 +849,16 @@ export const language = P.createLanguage({ ], 2).map(name => M.EMOJI_CODE(name as string)); }, + /** + * A {@link P.Parser Parser} that matches inline links, which are made up of the label and the url. + * The label must be opened with either `?[` for silent links or `[` for normal links and closed with `]`. + * The url must be opened with `(` and closed with `)`, and the contents of the url must follow either the + * {@link language.url} or {@link language.urlAlt} rules. + * The inline link must be on a single line, but has no other restrictions on placement. + * + * @param r The rules of SFM + * @returns A {@link P.Parser Parser} for this rule + */ link: r => { const labelInline = new P.Parser((input, index, state) => { state.linkLabel = true; @@ -659,6 +886,12 @@ export const language = P.createLanguage({ }); }, + /** + * A {@link P.Parser Parser} that matches the standard format for urls. + * + * @param r The rules of SFM + * @returns A {@link P.Parser Parser} for this rule + */ url: r => { const urlChar = P.regexp(/[.,a-z0-9_/:%#@$&?!~=+-]/i); const innerItem: P.Parser = P.lazy(() => P.alt([ @@ -698,6 +931,12 @@ export const language = P.createLanguage({ }); }, + /** + * A {@link P.Parser Parser} that matches an alternate form for urls, where it is opened with `<` and closed with `>`. + * + * @param r The rules of SFM + * @returns A {@link P.Parser Parser} for this rule + */ urlAlt: r => { const open = P.str('<'); const close = P.str('>'); @@ -718,6 +957,14 @@ export const language = P.createLanguage({ }); }, + /** + * A {@link P.Parser Parser} that matches single line text for a search query. The query must have either `[検索]` or + * `[search]` at the end of the line. + * The query and button must be on the same line and there can be nothing else on that line. + * + * @param r The rules of SFM + * @returns A {@link P.Parser Parser} for this rule + */ search: r => { const button = P.alt([ P.regexp(/\[(検索|search)\]/i), @@ -742,5 +989,11 @@ export const language = P.createLanguage({ }); }, + /** + * A rule that simply collects characters. + * + * @param r The rules of SFM + * @returns A {@link P.Parser Parser} for this rule + */ text: r => P.char, }); From 81b70aefc70f66651d7fffb55483d3bc4e19708f Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Tue, 9 Apr 2024 12:52:50 -0400 Subject: [PATCH 2/3] Updated documentation with suggested changes --- src/internal/core/index.ts | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/internal/core/index.ts b/src/internal/core/index.ts index 89e23df..1c50fe7 100644 --- a/src/internal/core/index.ts +++ b/src/internal/core/index.ts @@ -22,7 +22,7 @@ export type Failure = { success: false }; export type Result = Success | Failure; /** - * The function used by a parser to determine if it succeeds or fails. + * The function used by a parser */ export type ParserHandler = (input: string, index: number, state: any) => Result @@ -78,7 +78,7 @@ export class Parser { } /** - * A function that maps the result of the parse with the provided function if successful, and returns a {@link Failure} + * A method that maps the result of the parse with the provided function if successful, and returns a {@link Failure} * otherwise. * * @param fn The function used to map the output of the parser. @@ -95,7 +95,8 @@ export class Parser { } /** - * A function that returns the plaintext related to the {@link Success} and a {@link Failure} otherwise. + * A method that returns the portion of the input that matches this {@link Parser Parser's} language and a {@link Failure} + * if the parse failed. * * @returns The plaintext related to the successful parse, and a {@link Failure} if the parse failed. */ @@ -111,8 +112,7 @@ export class Parser { } /** - * A function that returns a {@link Parser} that must succeed at least of `min` times in order to return - * a {@link Success} and returns a {@link Failure} otherwise. + * A method that returns a {@link Parser} that matches at least `min` repetitions of this parser. * * @param min The minimum amount of times this parse must succeed to return a {@link Success}. * @returns A Parser that returns a {@link Success} object it matches enough times, and a {@link Failure} otherwise. @@ -138,7 +138,8 @@ export class Parser { } /** - * A function that checks if the supplied separator appears between this separator's value. + * A method that returns a new {@link Parser} that matches at least `min` times, with each repetition separated + * by `separator`. * * @param separator The parser representing the separator that must appear between this parser's value. * @param min The minimum amount of times the separator must appear. @@ -158,8 +159,8 @@ export class Parser { } /** - * A function that attempts to match this parser, but returns a {@link Success} object with the - * value `null` if it fails. + * A method that returns a new {@link Parser} that attempts to match, but returns a {@link Success} with the value `null` + * on failure. * * @returns A {@link Success} object. */ @@ -239,10 +240,8 @@ export function seq(parsers: Parser[], select?: number): Parser { } /** - * A function that returns a {@link Parser} that goes through the parsers provided, in order, and checks if each succeeds. - * If one fails, the next parser is tested, and this pattern is continued until the final parser is tested, at which point - * the parser will return a {@link Failure} if it still fails. If any of the parsers succeed, the resulting {@link Success} - * is returned immediately. + * A function that returns a {@link Parser} that goes through the parsers provided, in order, and checks if any succeed. + * The returned parser produces the result of the first element of `parsers` to succeed, or a failure if none do. * * @param parsers The {@link Parser Parsers} that should be used. * @returns A {@link Parser} that returns the first {@link Success} from the supplied parsers. @@ -261,7 +260,7 @@ export function alt(parsers: Parser[]): Parser { } /** - * A function that returns a {@link Parser} that always succeeds, returning a {@link Success} object with the supplied value. + * A function that returns a constant {@link Parser}. * * @param value The value to be used in the returned {@link Success} object. * @returns A {@link Parser} that always returns a {@link Success} with the specified value. @@ -317,7 +316,10 @@ export const crlf = str('\r\n'); /** A {@link Parser} that matches for any valid new line sequences. */ export const newline = alt([crlf, cr, lf]); -/** A {@link Parser} that succeeds so long as it is not at the end of the input string. */ +/** + * A {@link Parser} that succeeds so long as it is not at the end of the input string and returns the value of + * the next character. + */ export const char = new Parser((input, index, _state) => { if ((input.length - index) < 1) { return failure(); From 488444ccbf37ca02e9016c40f7c18541bd86cd0a Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Tue, 9 Apr 2024 13:33:01 -0400 Subject: [PATCH 3/3] Applied suggestions to other files' documentation --- src/internal/index.ts | 4 ++-- src/internal/parser.ts | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/internal/index.ts b/src/internal/index.ts index 8ccd5b6..b9406e1 100644 --- a/src/internal/index.ts +++ b/src/internal/index.ts @@ -11,7 +11,7 @@ export type FullParserOpts = { }; /** - * A function that parses through the input plaintext with the full parser and returns the AST representing the + * A function that parses through the input text with the full parser and returns the AST representing the * result. * * @param input The input string to parse. @@ -29,7 +29,7 @@ export function fullParser(input: string, opts: FullParserOpts): M.MfmNode[] { } /** - * A function that parses through the input plaintext with the simple parser and returns the AST representing the + * A function that parses through the input text with the simple parser and returns the AST representing the * result. * * @param input The input string to parse. diff --git a/src/internal/parser.ts b/src/internal/parser.ts index 7ffffae..ac64553 100644 --- a/src/internal/parser.ts +++ b/src/internal/parser.ts @@ -21,15 +21,15 @@ const newLine = P.alt([P.crlf, P.cr, P.lf]); /** * A function that returns a {@link P.Parser Parser} which goes through the supplied parsers sequentially. - * If the first provided parser fails, a {@link P.Failure Failure} object is returned, the plaintext of the - * successfully parsed portion of the input if any other parsers fail, and an array of the values of the - * parsers' {@link P.Success Successes}. + * If the first provided parser fails, a {@link P.Failure Failure} object is returned, the matched portion of the + * input text is returned if any other parsers fail, and an array of the values of the parsers' + * {@link P.Success Successes}. * * @param parsers The list of {@link P.Parser Parsers} to use. * @returns A {@link P.Parser Parser} that goes through the supplied parsers sequentially and makes sure that each * succeeds. If the first parser fails, a {@link P.Failure Failure} object is returned. If any other parser - * fails, the plaintext of the successfully parsed portion of the input text is returned. If all succeed, - * the array of each {@link P.Success Success'} value is returned. + * fails, the matched portion of the input text is returned. If all succeed, the array of each + * {@link P.Success Success'} value is returned. */ function seqOrText(parsers: P.Parser[]): P.Parser { return new P.Parser((input, index, state) => {