slack-message-parser
Advanced tools
Comparing version 3.0.1 to 3.0.2
@@ -13,2 +13,20 @@ export const or = (parsers) => { | ||
}; | ||
export const oneOrMore = (parser, andThen) => { | ||
const rec = (text, position, rootParser) => { | ||
const match = parser(text, position, rootParser); | ||
if (!match) { | ||
return []; | ||
} | ||
const [, nextPosition] = match; | ||
return [match, ...rec(text, nextPosition, rootParser)]; | ||
}; | ||
return (text, position, rootParser) => { | ||
const ret = rec(text, position, rootParser); | ||
if (ret.length === 0) { | ||
return null; | ||
} | ||
const [, lastPosition] = ret[ret.length - 1]; | ||
return [andThen(ret.map(([a]) => a)), lastPosition]; | ||
}; | ||
}; | ||
export const regexp = (pattern, callback) => (text, position, parseText) => { | ||
@@ -15,0 +33,0 @@ const match = text.substring(position).match(pattern); |
import { NodeType } from "./types/Node.js"; | ||
import { explicit, or, regexp, topOfLine } from "./combinator.js"; | ||
import { explicit, oneOrMore, or, regexp, topOfLine } from "./combinator.js"; | ||
const parseBold = explicit(regexp(/^\*(\S([^*\n]*?|[^*\n]*? `.*?` )[^\s*]|\S)\*(?=[\s~!#$%^)\-+={}[\];:'",.?/]|$)/, (match, _text, position, parseText) => { | ||
@@ -58,5 +58,11 @@ const [matchedText, content] = match; | ||
})); | ||
const parseSingleLineQuote = topOfLine(regexp(/^>(.*)(\n|$)/, (match, _text, position, parseText) => { | ||
const parseQuoteLine = topOfLine(regexp(/^>(.*)(\n>|\n|$)/, (match, _text, position, parseText) => { | ||
const [matchedText, content] = match; | ||
const repeatedGt = content.match(/^((>)+)(.*)$/); | ||
// If the next line is also starts with ">", do not include the character | ||
// (simulating RegExp's non-capturing group) | ||
const source = matchedText.replace(/\n>$/, "\n"); | ||
// `source` and `matchedText` are same unless the next line starts with ">" | ||
// due to the above line removes the ">". | ||
const isNextLineStartsWithGt = source !== matchedText; | ||
return [ | ||
@@ -74,19 +80,30 @@ { | ||
] | ||
: parseText(content), | ||
source: matchedText, | ||
// Only the last LF could be a terminator character of quote. | ||
// Non-last LFs should be parsed as well as `content`. | ||
: parseText(isNextLineStartsWithGt ? content + "\n" : content), | ||
source, | ||
}, | ||
position + matchedText.length, | ||
position + source.length, | ||
]; | ||
})); | ||
const parseMultilineQuote = topOfLine(regexp(/^>>>([\s\S]+)$/, (match, _text, position, parseText) => { | ||
const [matchedText, content] = match; | ||
return [ | ||
{ | ||
const parseQuote = or([ | ||
topOfLine(regexp(/^>>>([\s\S]+)$/, (match, _text, position, parseText) => { | ||
const [matchedText, content] = match; | ||
return [ | ||
{ | ||
type: NodeType.Quote, | ||
children: parseText(content), | ||
source: matchedText, | ||
}, | ||
position + matchedText.length, | ||
]; | ||
})), | ||
oneOrMore(parseQuoteLine, (quotes) => { | ||
return { | ||
type: NodeType.Quote, | ||
children: parseText(content), | ||
source: matchedText, | ||
}, | ||
position + matchedText.length, | ||
]; | ||
})); | ||
children: quotes.map((quote) => quote.children).flat(), | ||
source: quotes.map((quote) => quote.source).join(""), | ||
}; | ||
}), | ||
]); | ||
const parseEmoji = regexp(/^:([^:<`*#@!\s()$%]+):(:(skin-tone-.+?):)?/, (match, _text, position) => { | ||
@@ -160,6 +177,5 @@ const [matchedText, name, _, variation] = match; | ||
parseItalic, | ||
parseMultilineQuote, | ||
parseSingleLineQuote, | ||
parseQuote, | ||
parseLink, | ||
parseStrike, | ||
]); |
@@ -6,3 +6,3 @@ { | ||
"name": "slack-message-parser", | ||
"version": "3.0.1", | ||
"version": "v3.0.2", | ||
"description": "Parser for Slack message", | ||
@@ -9,0 +9,0 @@ "repository": { |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.topOfLine = exports.explicit = exports.regexp = exports.or = void 0; | ||
exports.topOfLine = exports.explicit = exports.regexp = exports.oneOrMore = exports.or = void 0; | ||
const or = (parsers) => { | ||
@@ -17,2 +17,21 @@ const { length } = parsers; | ||
exports.or = or; | ||
const oneOrMore = (parser, andThen) => { | ||
const rec = (text, position, rootParser) => { | ||
const match = parser(text, position, rootParser); | ||
if (!match) { | ||
return []; | ||
} | ||
const [, nextPosition] = match; | ||
return [match, ...rec(text, nextPosition, rootParser)]; | ||
}; | ||
return (text, position, rootParser) => { | ||
const ret = rec(text, position, rootParser); | ||
if (ret.length === 0) { | ||
return null; | ||
} | ||
const [, lastPosition] = ret[ret.length - 1]; | ||
return [andThen(ret.map(([a]) => a)), lastPosition]; | ||
}; | ||
}; | ||
exports.oneOrMore = oneOrMore; | ||
const regexp = (pattern, callback) => (text, position, parseText) => { | ||
@@ -19,0 +38,0 @@ const match = text.substring(position).match(pattern); |
@@ -60,5 +60,11 @@ "use strict"; | ||
})); | ||
const parseSingleLineQuote = (0, combinator_js_1.topOfLine)((0, combinator_js_1.regexp)(/^>(.*)(\n|$)/, (match, _text, position, parseText) => { | ||
const parseQuoteLine = (0, combinator_js_1.topOfLine)((0, combinator_js_1.regexp)(/^>(.*)(\n>|\n|$)/, (match, _text, position, parseText) => { | ||
const [matchedText, content] = match; | ||
const repeatedGt = content.match(/^((>)+)(.*)$/); | ||
// If the next line is also starts with ">", do not include the character | ||
// (simulating RegExp's non-capturing group) | ||
const source = matchedText.replace(/\n>$/, "\n"); | ||
// `source` and `matchedText` are same unless the next line starts with ">" | ||
// due to the above line removes the ">". | ||
const isNextLineStartsWithGt = source !== matchedText; | ||
return [ | ||
@@ -76,19 +82,30 @@ { | ||
] | ||
: parseText(content), | ||
source: matchedText, | ||
// Only the last LF could be a terminator character of quote. | ||
// Non-last LFs should be parsed as well as `content`. | ||
: parseText(isNextLineStartsWithGt ? content + "\n" : content), | ||
source, | ||
}, | ||
position + matchedText.length, | ||
position + source.length, | ||
]; | ||
})); | ||
const parseMultilineQuote = (0, combinator_js_1.topOfLine)((0, combinator_js_1.regexp)(/^>>>([\s\S]+)$/, (match, _text, position, parseText) => { | ||
const [matchedText, content] = match; | ||
return [ | ||
{ | ||
const parseQuote = (0, combinator_js_1.or)([ | ||
(0, combinator_js_1.topOfLine)((0, combinator_js_1.regexp)(/^>>>([\s\S]+)$/, (match, _text, position, parseText) => { | ||
const [matchedText, content] = match; | ||
return [ | ||
{ | ||
type: Node_js_1.NodeType.Quote, | ||
children: parseText(content), | ||
source: matchedText, | ||
}, | ||
position + matchedText.length, | ||
]; | ||
})), | ||
(0, combinator_js_1.oneOrMore)(parseQuoteLine, (quotes) => { | ||
return { | ||
type: Node_js_1.NodeType.Quote, | ||
children: parseText(content), | ||
source: matchedText, | ||
}, | ||
position + matchedText.length, | ||
]; | ||
})); | ||
children: quotes.map((quote) => quote.children).flat(), | ||
source: quotes.map((quote) => quote.source).join(""), | ||
}; | ||
}), | ||
]); | ||
const parseEmoji = (0, combinator_js_1.regexp)(/^:([^:<`*#@!\s()$%]+):(:(skin-tone-.+?):)?/, (match, _text, position) => { | ||
@@ -162,6 +179,5 @@ const [matchedText, name, _, variation] = match; | ||
parseItalic, | ||
parseMultilineQuote, | ||
parseSingleLineQuote, | ||
parseQuote, | ||
parseLink, | ||
parseStrike, | ||
]); |
import { Node } from "./types/Node.js"; | ||
import { Parser, ParseText } from "./types/Parser.js"; | ||
export declare const or: (parsers: Parser[]) => Parser; | ||
export declare const regexp: (pattern: RegExp, callback: (match: string[], text: string, position: number, parseText: ParseText) => [Node, number] | null) => Parser; | ||
export declare const oneOrMore: <A extends Node, B extends Node>(parser: Parser<A>, andThen: (nodes: readonly A[]) => B) => Parser<B>; | ||
export declare const regexp: <T extends Node = Node>(pattern: RegExp, callback: (match: string[], text: string, position: number, parseText: ParseText) => [T, number] | null) => Parser<T>; | ||
export declare const explicit: (parser: Parser) => Parser; | ||
export declare const topOfLine: (parser: Parser) => Parser; | ||
export declare const topOfLine: <T extends Node = Node>(parser: Parser<T>) => Parser<T>; |
import { Node } from "./Node.js"; | ||
export type Parser = (text: string, position: number, parseText: ParseText) => [Node, number] | null; | ||
export type Parser<T extends Node = Node> = (text: string, position: number, parseText: ParseText) => [T, number] | null; | ||
export type ParseText = (text: string) => Node[]; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
39334
884
1