You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

101 lines
3.9 KiB

/**
* Single source of truth for :emoji: shortcodes and nostr: bech32 patterns.
* Used by MarkdownArticle, parseContent, previews, post editor, AsciiDoc, etc.
*/
// --- Emoji (:shortcode:) ----------------------------------------------------
export const EMOJI_SHORT_CODE_MAX_INNER_LENGTH = 20 as const
const _emojiInnerQuantifier = EMOJI_SHORT_CODE_MAX_INNER_LENGTH - 1
/**
* - (?<!:) avoids AsciiDoc double-colon macros (link::, image::, citation::, etc.)
* - First char after ":" must be [a-zA-Z0-9_-] so "Name: nostr:npub…" is not ": nostr:"
* - Inner body max length so URLs/paths/nostr ids are not treated as shortcodes
*/
export const EMOJI_SHORT_CODE_REGEX = new RegExp(
`(?<!:):([a-zA-Z0-9_\\-][^:]{0,${_emojiInnerQuantifier}}):`,
'g'
)
// --- Nostr bech32 (after "nostr:") ------------------------------------------
/** Standard npub / note payload length in hex */
export const BECH32_NPUB = 'npub1[a-z0-9]{58}'
export const BECH32_NPROFILE = 'nprofile1[a-z0-9]+'
export const BECH32_NOTE = 'note1[a-z0-9]{58}'
export const BECH32_NEVENT = 'nevent1[a-z0-9]+'
export const BECH32_NADDR = 'naddr1[a-z0-9]+'
/** AsciiDoc / forgiving passes: allow longer npub/note encodings ({58,}) */
export const BECH32_NPUB_LOOSE = 'npub1[a-z0-9]{58,}'
export const BECH32_NOTE_LOOSE = 'note1[a-z0-9]{58,}'
/** All kinds we render from note content (strict lengths for Markdown / parseContent) */
export const NOSTR_CONTENT_BECH32_ALT = [
BECH32_NPUB,
BECH32_NPROFILE,
BECH32_NOTE,
BECH32_NEVENT,
BECH32_NADDR
].join('|')
/** AsciiDoc early conversion + text-node extraction (loose npub/note) */
export const NOSTR_ASCIIDOC_SOURCE_BECH32_ALT = [
BECH32_NPUB_LOOSE,
BECH32_NPROFILE,
BECH32_NOTE_LOOSE,
BECH32_NEVENT,
BECH32_NADDR
].join('|')
/** Relaxed tail for HTML href / fallback matching (naddr can be very long) */
export const NOSTR_HTML_BECH32_RELAXED = '(?:npub1|nprofile1|note1|nevent1|naddr1)[a-z0-9]{20,}'
export const NOSTR_PROFILE_BECH32_ALT = [BECH32_NPUB, BECH32_NPROFILE].join('|')
export const NOSTR_EVENT_BECH32_ALT = [BECH32_NOTE, BECH32_NEVENT, BECH32_NADDR].join('|')
export const NOSTR_NOTE_AND_NEVENT_ALT = [BECH32_NOTE, BECH32_NEVENT].join('|')
/** nostr:… anywhere in text (Markdown inline, relay scan, editor, preprocess) */
export const NOSTR_URI_INLINE_REGEX = new RegExp(`nostr:(${NOSTR_CONTENT_BECH32_ALT})`, 'g')
/** parseContent: profile mentions only */
export const EMBEDDED_MENTION_REGEX = new RegExp(`nostr:(${NOSTR_PROFILE_BECH32_ALT})`, 'g')
/** parseContent: embedded notes (note / nevent / naddr) */
export const EMBEDDED_EVENT_REGEX = new RegExp(`nostr:(${NOSTR_EVENT_BECH32_ALT})`, 'g')
/** event helpers: note + nevent only */
export const NOSTR_EMBEDDED_NOTE_REGEX = new RegExp(`nostr:(${NOSTR_NOTE_AND_NEVENT_ALT})`, 'g')
/** naddr-only (e.g. URL / deep links) */
export const NOSTR_URI_NADDR_REGEX = new RegExp(`nostr:(${BECH32_NADDR})`, 'g')
/** Post editor / reply pubkey scan: npub, nprofile, note, nevent (not naddr) */
export const NOSTR_URI_FOR_REPLY_PUBKEYS_REGEX = new RegExp(
`nostr:(${[BECH32_NPUB, BECH32_NPROFILE, BECH32_NOTE, BECH32_NEVENT].join('|')})`,
'g'
)
/** Legacy bare bech32 (no nostr: prefix) */
export const LEGACY_PROFILE_BECH32_REGEX = new RegExp(`${BECH32_NPUB}|${BECH32_NPROFILE}`, 'g')
/** Boundary + lookahead so punctuation does not stick to bech32 */
export const NOSTR_PARSER_LOOKAHEAD = '(?=\\s|$|>|\\]|,|\\.|!|\\?|;|:)'
export const NOSTR_PARSER_REGEX = new RegExp(
`(?:^|\\s|>|\\[)nostr:(${NOSTR_CONTENT_BECH32_ALT})${NOSTR_PARSER_LOOKAHEAD}`,
'g'
)
/** AsciiDoc: optional [] after nostr id */
export const NOSTR_ASCIIDOC_EARLY_LINK_REGEX = new RegExp(
`nostr:(${NOSTR_ASCIIDOC_SOURCE_BECH32_ALT})(\\[\\])?`,
'g'
)
/** AsciiDoc HTML: same capture groups as early link, for text-node scanning */
export const NOSTR_ASCIIDOC_TEXT_NODE_REGEX = new RegExp(
`nostr:(${NOSTR_ASCIIDOC_SOURCE_BECH32_ALT})(\\[\\])?`,
'g'
)