Fix parser bugs, fix repository delete
This commit is contained in:
+35
-46
@@ -5,6 +5,9 @@ const last = <T>(xs: T[], ...args: unknown[]) => xs[xs.length - 1]
|
||||
|
||||
const fromNostrURI = (s: string) => s.replace(/^nostr:\/?\/?/, "")
|
||||
|
||||
export const urlIsMedia = (url: string) =>
|
||||
Boolean(url.match(/\.(jpe?g|png|wav|mp3|mp4|mov|avi|webm|webp|gif|bmp|svg)$/))
|
||||
|
||||
// Copy some types from nostr-tools because I can't import them
|
||||
|
||||
type AddressPointer = {
|
||||
@@ -37,8 +40,7 @@ export type ParseContext = {
|
||||
export enum ParsedType {
|
||||
Address = "address",
|
||||
Cashu = "cashu",
|
||||
CodeBlock = "code_block",
|
||||
CodeInline = "code_inline",
|
||||
Code = "code",
|
||||
Ellipsis = "ellipsis",
|
||||
Event = "event",
|
||||
Invoice = "invoice",
|
||||
@@ -55,14 +57,8 @@ export type ParsedCashu = {
|
||||
raw: string
|
||||
}
|
||||
|
||||
export type ParsedCodeBlock = {
|
||||
type: ParsedType.CodeBlock
|
||||
value: string
|
||||
raw: string
|
||||
}
|
||||
|
||||
export type ParsedCodeInline = {
|
||||
type: ParsedType.CodeInline
|
||||
export type ParsedCode = {
|
||||
type: ParsedType.Code
|
||||
value: string
|
||||
raw: string
|
||||
}
|
||||
@@ -130,8 +126,7 @@ export type ParsedAddress = {
|
||||
export type Parsed =
|
||||
ParsedAddress |
|
||||
ParsedCashu |
|
||||
ParsedCodeBlock |
|
||||
ParsedCodeInline |
|
||||
ParsedCode |
|
||||
ParsedEllipsis |
|
||||
ParsedEvent |
|
||||
ParsedInvoice |
|
||||
@@ -141,6 +136,20 @@ export type Parsed =
|
||||
ParsedText |
|
||||
ParsedTopic
|
||||
|
||||
// Matchers
|
||||
|
||||
export const isAddress = (parsed: Parsed): parsed is ParsedAddress => parsed.type === ParsedType.Address
|
||||
export const isCashu = (parsed: Parsed): parsed is ParsedCashu => parsed.type === ParsedType.Cashu
|
||||
export const isCode = (parsed: Parsed): parsed is ParsedCode => parsed.type === ParsedType.Code
|
||||
export const isEllipsis = (parsed: Parsed): parsed is ParsedEllipsis => parsed.type === ParsedType.Ellipsis
|
||||
export const isEvent = (parsed: Parsed): parsed is ParsedEvent => parsed.type === ParsedType.Event
|
||||
export const isInvoice = (parsed: Parsed): parsed is ParsedInvoice => parsed.type === ParsedType.Invoice
|
||||
export const isLink = (parsed: Parsed): parsed is ParsedLink => parsed.type === ParsedType.Link
|
||||
export const isNewline = (parsed: Parsed): parsed is ParsedNewline => parsed.type === ParsedType.Newline
|
||||
export const isProfile = (parsed: Parsed): parsed is ParsedProfile => parsed.type === ParsedType.Profile
|
||||
export const isText = (parsed: Parsed): parsed is ParsedText => parsed.type === ParsedType.Text
|
||||
export const isTopic = (parsed: Parsed): parsed is ParsedTopic => parsed.type === ParsedType.Topic
|
||||
|
||||
// Parsers for known formats
|
||||
|
||||
export const parseAddress = (text: string, context: ParseContext): ParsedAddress | void => {
|
||||
@@ -165,19 +174,19 @@ export const parseCashu = (text: string, context: ParseContext): ParsedCashu | v
|
||||
}
|
||||
}
|
||||
|
||||
export const parseCodeBlock = (text: string, context: ParseContext): ParsedCodeBlock | void => {
|
||||
export const parseCodeBlock = (text: string, context: ParseContext): ParsedCode | void => {
|
||||
const [code, value] = text.match(/^```([^]*?)```/i) || []
|
||||
|
||||
if (code) {
|
||||
return {type: ParsedType.CodeBlock, value, raw: code}
|
||||
return {type: ParsedType.Code, value, raw: code}
|
||||
}
|
||||
}
|
||||
|
||||
export const parseCodeInline = (text: string, context: ParseContext): ParsedCodeInline | void => {
|
||||
export const parseCodeInline = (text: string, context: ParseContext): ParsedCode | void => {
|
||||
const [code, value] = text.match(/^`(.*?)`/i) || []
|
||||
|
||||
if (code) {
|
||||
return {type: ParsedType.CodeInline, value, raw: code}
|
||||
return {type: ParsedType.Code, value, raw: code}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,28 +216,18 @@ export const parseInvoice = (text: string, context: ParseContext): ParsedInvoice
|
||||
}
|
||||
|
||||
export const parseLink = (text: string, context: ParseContext): ParsedLink | void => {
|
||||
let [link] = text.match(/^([a-z\+:]{2,30}:\/\/)?[^<>\(\)\s]+\.[a-z]{2,6}[^\s]*[^<>"'\.!?,:\s\)\(]/gi) || []
|
||||
|
||||
if (!link) {
|
||||
return
|
||||
}
|
||||
|
||||
const prev = last(context.results)
|
||||
const [link] = text.match(/^([a-z\+:]{2,30}:\/\/)?[^<>\(\)\s]+\.[a-z]{2,6}[^\s]*[^<>"'\.!?,:\s\)\(]/gi) || []
|
||||
|
||||
// Skip url if it's just the end of a filepath or an ellipse
|
||||
if (prev?.type === ParsedType.Text && prev.value.endsWith("/") || link.match(/\.\./)) {
|
||||
if (!link || prev?.type === ParsedType.Text && prev.value.endsWith("/") || link.match(/\.\./)) {
|
||||
return
|
||||
}
|
||||
|
||||
// Make sure there's a protocol
|
||||
if (!link.match(/^\w+:\/\//)) {
|
||||
link = "https://" + link
|
||||
}
|
||||
|
||||
// Parse using URL
|
||||
// Parse using URL, make sure there's a protocol
|
||||
let url
|
||||
try {
|
||||
url = new URL(link)
|
||||
url = new URL(link.match(/^\w+:\/\//) ? link : "https://" + link)
|
||||
} catch (e) {
|
||||
return
|
||||
}
|
||||
@@ -241,13 +240,7 @@ export const parseLink = (text: string, context: ParseContext): ParsedLink | voi
|
||||
}
|
||||
}
|
||||
|
||||
const isMedia = Boolean(
|
||||
url.pathname.match(/\.(jpe?g|png|wav|mp3|mp4|mov|avi|webm|webp|gif|bmp|svg)$/)
|
||||
)
|
||||
|
||||
const value = {url, meta, isMedia}
|
||||
|
||||
return {type: ParsedType.Link, value, raw: link}
|
||||
return {type: ParsedType.Link, value: {url, meta, isMedia: urlIsMedia(url.pathname)}, raw: link}
|
||||
}
|
||||
|
||||
export const parseNewline = (text: string, context: ParseContext): ParsedNewline | void => {
|
||||
@@ -280,7 +273,7 @@ export const parseTopic = (text: string, context: ParseContext): ParsedTopic | v
|
||||
|
||||
// Skip numeric topics
|
||||
if (value && !value.match(/^#\d+$/)) {
|
||||
return {type: ParsedType.Topic, value, raw: value}
|
||||
return {type: ParsedType.Topic, value: value.slice(1), raw: value}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,19 +441,16 @@ export class HTML {
|
||||
HTML.useSafely(`<a href=${href} target="_blank">${display}</a>`)
|
||||
|
||||
static buildEntityLink = (entity: string, options: RenderOptions) =>
|
||||
HTML.buildLink(options.entityBaseUrl + entity, entity.slice(0, 16))
|
||||
HTML.buildLink(options.entityBaseUrl + entity, entity.slice(0, 16) + '…')
|
||||
}
|
||||
|
||||
export const renderCashu = (parsed: ParsedCashu, options: RenderOptions) =>
|
||||
HTML.useSafely(parsed.value)
|
||||
|
||||
export const renderCodeBlock = (parsed: ParsedCodeBlock, options: RenderOptions) =>
|
||||
export const renderCode = (parsed: ParsedCode, options: RenderOptions) =>
|
||||
HTML.useSafely(parsed.value)
|
||||
|
||||
export const renderCodeInline = (parsed: ParsedCodeInline, options: RenderOptions) =>
|
||||
HTML.useSafely(parsed.value)
|
||||
|
||||
export const renderEllipsis = (parsed: ParsedEllipsis, options: RenderOptions) => "..."
|
||||
export const renderEllipsis = (parsed: ParsedEllipsis, options: RenderOptions) => "…"
|
||||
|
||||
export const renderInvoice = (parsed: ParsedInvoice, options: RenderOptions) =>
|
||||
HTML.useSafely(parsed.value)
|
||||
@@ -496,8 +486,7 @@ export const render = (parsed: Parsed, options: RenderOptions = {}) => {
|
||||
switch (parsed.type) {
|
||||
case ParsedType.Address: return renderAddress(parsed as ParsedAddress, options)
|
||||
case ParsedType.Cashu: return renderCashu(parsed as ParsedCashu, options)
|
||||
case ParsedType.CodeBlock: return renderCodeBlock(parsed as ParsedCodeBlock, options)
|
||||
case ParsedType.CodeInline: return renderCodeInline(parsed as ParsedCodeInline, options)
|
||||
case ParsedType.Code: return renderCode(parsed as ParsedCode, options)
|
||||
case ParsedType.Ellipsis: return renderEllipsis(parsed as ParsedEllipsis, options)
|
||||
case ParsedType.Event: return renderEvent(parsed as ParsedEvent, options)
|
||||
case ParsedType.Invoice: return renderInvoice(parsed as ParsedInvoice, options)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@welshman/content",
|
||||
"version": "0.0.2",
|
||||
"version": "0.0.3",
|
||||
"author": "hodlbod",
|
||||
"license": "MIT",
|
||||
"description": "A collection of utilities for parsing nostr note content.",
|
||||
|
||||
Reference in New Issue
Block a user