applesauce-content 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,8 @@
1
1
  import { getSha256FromURL } from "applesauce-core/helpers/file-metadata";
2
- import Expressions from "./regexp.js";
2
+ import { Tokens } from "./regexp.js";
3
3
  /** Returns all URLs in a content string that contain a sha256 hash */
4
4
  export function getMediaAttachmentURLsFromContent(content) {
5
- return (Array.from(content.matchAll(Expressions.link))
5
+ return (Array.from(content.matchAll(Tokens.link))
6
6
  .map((match) => match[0])
7
7
  // filter out invalid URLs
8
8
  .filter((str) => URL.canParse(str))
@@ -1,4 +1,15 @@
1
1
  export declare const Expressions: {
2
+ readonly url: RegExp;
3
+ readonly link: RegExp;
4
+ readonly cashu: RegExp;
5
+ readonly nostrLink: RegExp;
6
+ readonly emoji: RegExp;
7
+ readonly hashtag: RegExp;
8
+ readonly lightning: RegExp;
9
+ };
10
+ /** A list of Regular Expressions that match tokens surrounded by whitespace to avoid matching in URLs */
11
+ export declare const Tokens: {
12
+ readonly url: RegExp;
2
13
  readonly link: RegExp;
3
14
  readonly cashu: RegExp;
4
15
  readonly nostrLink: RegExp;
@@ -6,4 +17,3 @@ export declare const Expressions: {
6
17
  readonly hashtag: RegExp;
7
18
  readonly lightning: RegExp;
8
19
  };
9
- export default Expressions;
@@ -1,21 +1,48 @@
1
1
  export const Expressions = {
2
+ get url() {
3
+ return /(?:https?|wss?|ircs?|s?ftp):\/\/([a-zA-Z0-9\.\-]+\.[a-zA-Z]+(?::\d+)?)([\/\?#][\p{L}\p{N}\p{M}&\.-\/\?=#\-@%\+_,:!~*]*)?/gu;
4
+ },
2
5
  get link() {
3
6
  return /https?:\/\/([a-zA-Z0-9\.\-]+\.[a-zA-Z]+(?::\d+)?)([\/\?#][\p{L}\p{N}\p{M}&\.-\/\?=#\-@%\+_,:!~*]*)?/gu;
4
7
  },
5
8
  get cashu() {
6
- return /(cashu(?:A|B)[A-Za-z0-9_-]{100,10000}={0,3})/gi;
9
+ return /(?:cashu:\/{0,2})?(cashu(?:A|B)[A-Za-z0-9_-]{100,10000}={0,3})/gi;
7
10
  },
8
11
  get nostrLink() {
9
- return /nostr:((npub|note|nprofile|nevent|naddr)1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{58,})/gi;
12
+ return /(?:nostr:)?((npub|note|nprofile|nevent|naddr)1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{58,})/gi;
10
13
  },
11
14
  get emoji() {
12
15
  return /:([a-zA-Z0-9_-]+):/gi;
13
16
  },
14
17
  get hashtag() {
15
- return /(?<=^|[^\p{L}#])#([\p{L}\p{N}\p{M}]+)/gu;
18
+ // NOTE: cant use \b here because it uses \w which only matches latin letters
19
+ return /(?<=^|[^\p{L}#\/])#([\p{L}\p{N}\p{M}]+)(?=\p{Z}|$|\s)/gu;
16
20
  },
17
21
  get lightning() {
18
22
  return /(?:lightning:)?(LNBC[A-Za-z0-9]+)/gim;
19
23
  },
20
24
  };
21
- export default Expressions;
25
+ /** A list of Regular Expressions that match tokens surrounded by whitespace to avoid matching in URLs */
26
+ export const Tokens = {
27
+ get url() {
28
+ return Expressions.url;
29
+ },
30
+ get link() {
31
+ return Expressions.link;
32
+ },
33
+ get cashu() {
34
+ return new RegExp(`(?<=^|\\s)${Expressions.cashu.source}`, "gi");
35
+ },
36
+ get nostrLink() {
37
+ return new RegExp(`(?<=^|\\s)${Expressions.nostrLink.source}`, "gi");
38
+ },
39
+ get emoji() {
40
+ return Expressions.emoji;
41
+ },
42
+ get hashtag() {
43
+ return Expressions.hashtag;
44
+ },
45
+ get lightning() {
46
+ return new RegExp(`(?<=^|\\s)${Expressions.lightning.source}`, "gim");
47
+ },
48
+ };
@@ -1,6 +1,6 @@
1
- import { Transformer } from "unified";
1
+ import { DecodeResult } from "applesauce-core/helpers";
2
2
  import { Link, Nodes } from "mdast";
3
- import { DecodeResult } from "nostr-tools/nip19";
3
+ import { Transformer } from "unified";
4
4
  export interface NostrMention extends Link {
5
5
  type: "link";
6
6
  data: DecodeResult;
@@ -1,10 +1,10 @@
1
1
  import { findAndReplace } from "mdast-util-find-and-replace";
2
2
  import { decode } from "nostr-tools/nip19";
3
- import Expressions from "../helpers/regexp.js";
3
+ import { Tokens } from "../helpers/regexp.js";
4
4
  export function remarkNostrMentions() {
5
5
  return (tree) => {
6
6
  findAndReplace(tree, [
7
- Expressions.nostrLink,
7
+ Tokens.nostrLink,
8
8
  (_, $1) => {
9
9
  try {
10
10
  return {
@@ -1,8 +1,8 @@
1
- import { EventTemplate, NostrEvent } from "nostr-tools";
2
- import { DecodeResult } from "nostr-tools/nip19";
3
- import { Node as UnistNode, Parent } from "unist";
4
1
  import { type Token } from "@cashu/cashu-ts";
2
+ import { type DecodeResult } from "applesauce-core/helpers";
5
3
  import { type ParsedInvoice } from "applesauce-core/helpers/bolt11";
4
+ import { type EventTemplate, type NostrEvent } from "nostr-tools";
5
+ import { type Parent, type Node as UnistNode } from "unist";
6
6
  export interface CommonData {
7
7
  eol?: boolean;
8
8
  }
@@ -43,7 +43,8 @@ export interface Hashtag extends Node {
43
43
  name: string;
44
44
  /** The lowercase canonical name */
45
45
  hashtag: string;
46
- tag: ["t", ...string[]];
46
+ /** The indexable tag for the hashtag. will be undefined if none was found */
47
+ tag?: ["t", ...string[]];
47
48
  }
48
49
  export interface Emoji extends Node {
49
50
  type: "emoji";
@@ -1,12 +1,12 @@
1
1
  import { getDecodedToken } from "@cashu/cashu-ts";
2
- import Expressions from "../helpers/regexp.js";
2
+ import { Tokens } from "../helpers/regexp.js";
3
3
  import { findAndReplace } from "../nast/find-and-replace.js";
4
4
  /** Parse cashu tokens from an ATS tree */
5
5
  export function cashuTokens() {
6
6
  return (tree) => {
7
7
  findAndReplace(tree, [
8
8
  [
9
- Expressions.cashu,
9
+ Tokens.cashu,
10
10
  (_, $1) => {
11
11
  try {
12
12
  const token = getDecodedToken($1);
@@ -3,7 +3,7 @@ import { getOrComputeCachedValue } from "applesauce-core/helpers/cache";
3
3
  import { nostrMentions } from "./mentions.js";
4
4
  import { cashuTokens } from "./cashu.js";
5
5
  import { emojis } from "./emoji.js";
6
- import { createTextNoteATS } from "./parser.js";
6
+ import { createEventContentTree } from "./parser.js";
7
7
  import { hashtags } from "./hashtag.js";
8
8
  import { galleries } from "./gallery.js";
9
9
  import { lightningInvoices } from "./lightning.js";
@@ -29,7 +29,7 @@ export function getParsedContent(event, content, transformers = textNoteTransfor
29
29
  for (const transformer of transformers) {
30
30
  processor.use(transformer);
31
31
  }
32
- return processor.runSync(createTextNoteATS(event, content));
32
+ return processor.runSync(createEventContentTree(event, content));
33
33
  }
34
34
  // no caching
35
35
  if (!cacheKey) {
@@ -37,14 +37,14 @@ export function getParsedContent(event, content, transformers = textNoteTransfor
37
37
  for (const transformer of transformers) {
38
38
  processor.use(transformer);
39
39
  }
40
- return processor.runSync(createTextNoteATS(event, content));
40
+ return processor.runSync(createEventContentTree(event, content));
41
41
  }
42
42
  return getOrComputeCachedValue(event, cacheKey, () => {
43
43
  const processor = unified();
44
44
  for (const transformer of transformers) {
45
45
  processor.use(transformer);
46
46
  }
47
- return processor.runSync(createTextNoteATS(event, content));
47
+ return processor.runSync(createEventContentTree(event, content));
48
48
  });
49
49
  }
50
50
  export function removeParsedTextContent(event) {
@@ -1,4 +1,4 @@
1
1
  import { type Transformer } from "unified";
2
2
  import { Root } from "../nast/types.js";
3
- /** Adds emoji tags to text ATS */
3
+ /** Finds and creates emoji nodes in the tree */
4
4
  export declare function emojis(): Transformer<Root>;
@@ -1,7 +1,7 @@
1
1
  import { getEmojiTag } from "applesauce-core/helpers/emoji";
2
- import Expressions from "../helpers/regexp.js";
2
+ import { Tokens } from "../helpers/regexp.js";
3
3
  import { findAndReplace } from "../nast/find-and-replace.js";
4
- /** Adds emoji tags to text ATS */
4
+ /** Finds and creates emoji nodes in the tree */
5
5
  export function emojis() {
6
6
  return (tree) => {
7
7
  const event = tree.event;
@@ -9,7 +9,7 @@ export function emojis() {
9
9
  return;
10
10
  findAndReplace(tree, [
11
11
  [
12
- Expressions.emoji,
12
+ Tokens.emoji,
13
13
  (full, $1) => {
14
14
  try {
15
15
  const tag = getEmojiTag(event, $1);
@@ -1,4 +1,4 @@
1
1
  import { Transformer } from "unified";
2
2
  import { Root } from "../nast/types.js";
3
- /** Groups images into galleries in an ATS tree */
3
+ /** Group images into galleries in an ATS tree */
4
4
  export declare function galleries(types?: string[]): Transformer<Root>;
@@ -1,5 +1,5 @@
1
1
  import { convertToUrl, getURLFilename, IMAGE_EXT } from "applesauce-core/helpers/url";
2
- /** Groups images into galleries in an ATS tree */
2
+ /** Group images into galleries in an ATS tree */
3
3
  export function galleries(types = IMAGE_EXT) {
4
4
  return (tree) => {
5
5
  let links = [];
@@ -1,3 +1,4 @@
1
1
  import { Transformer } from "unified";
2
2
  import { Root } from "../nast/types.js";
3
+ /** Find and create hashtag notes in provided tree */
3
4
  export declare function hashtags(): Transformer<Root>;
@@ -1,24 +1,24 @@
1
1
  import { getHashtagTag } from "applesauce-core/helpers/hashtag";
2
- import Expressions from "../helpers/regexp.js";
2
+ import { Tokens } from "../helpers/regexp.js";
3
3
  import { findAndReplace } from "../nast/find-and-replace.js";
4
+ /** Find and create hashtag notes in provided tree */
4
5
  export function hashtags() {
5
6
  return (tree) => {
6
7
  const event = tree.event;
7
- if (!event)
8
- return;
9
8
  findAndReplace(tree, [
10
9
  [
11
- Expressions.hashtag,
10
+ Tokens.hashtag,
12
11
  (_, $1) => {
13
12
  try {
14
- const tag = getHashtagTag(event, $1);
15
- if (!tag)
13
+ const tag = event && getHashtagTag(event, $1);
14
+ // Skip if the match if no tag was found in the event
15
+ if (!tag && event)
16
16
  return false;
17
17
  return {
18
18
  type: "hashtag",
19
19
  tag,
20
20
  name: $1,
21
- hashtag: tag[1].toLowerCase(),
21
+ hashtag: tag?.[1].toLowerCase() || $1.toLowerCase(),
22
22
  };
23
23
  }
24
24
  catch (error) { }
@@ -1,3 +1,4 @@
1
1
  import { type Transformer } from "unified";
2
2
  import { Root } from "../nast/types.js";
3
+ /** Finds and creates lightning invoice nodes in the tree */
3
4
  export declare function lightningInvoices(): Transformer<Root>;
@@ -1,11 +1,12 @@
1
1
  import { parseBolt11 } from "applesauce-core/helpers/bolt11";
2
- import Expressions from "../helpers/regexp.js";
2
+ import { Tokens } from "../helpers/regexp.js";
3
3
  import { findAndReplace } from "../nast/find-and-replace.js";
4
+ /** Finds and creates lightning invoice nodes in the tree */
4
5
  export function lightningInvoices() {
5
6
  return (tree) => {
6
7
  findAndReplace(tree, [
7
8
  [
8
- Expressions.lightning,
9
+ Tokens.lightning,
9
10
  (_, $1) => {
10
11
  try {
11
12
  const invoice = $1;
@@ -1,3 +1,4 @@
1
1
  import { Transformer } from "unified";
2
2
  import { Root } from "../nast/types.js";
3
+ /** Finds and creates web links in the tree */
3
4
  export declare function links(): Transformer<Root>;
@@ -1,10 +1,11 @@
1
- import Expressions from "../helpers/regexp.js";
1
+ import { Tokens } from "../helpers/regexp.js";
2
2
  import { findAndReplace } from "../nast/find-and-replace.js";
3
+ /** Finds and creates web links in the tree */
3
4
  export function links() {
4
5
  return (tree) => {
5
6
  findAndReplace(tree, [
6
7
  [
7
- Expressions.link,
8
+ Tokens.link,
8
9
  (_) => {
9
10
  try {
10
11
  return {
@@ -1,3 +1,4 @@
1
1
  import { Transformer } from "unified";
2
2
  import { Root } from "../nast/types.js";
3
+ /** Finds and creates NIP-19 nostr mentions in the tree */
3
4
  export declare function nostrMentions(): Transformer<Root>;
@@ -1,11 +1,12 @@
1
1
  import { decode } from "nostr-tools/nip19";
2
- import Expressions from "../helpers/regexp.js";
2
+ import { Tokens } from "../helpers/regexp.js";
3
3
  import { findAndReplace } from "../nast/find-and-replace.js";
4
+ /** Finds and creates NIP-19 nostr mentions in the tree */
4
5
  export function nostrMentions() {
5
6
  return (tree) => {
6
7
  findAndReplace(tree, [
7
8
  [
8
- Expressions.nostrLink,
9
+ Tokens.nostrLink,
9
10
  (_, $1) => {
10
11
  try {
11
12
  return {
@@ -1,4 +1,6 @@
1
1
  import { EventTemplate, NostrEvent } from "nostr-tools";
2
2
  import { Root } from "../nast/types.js";
3
3
  /** Creates a {@link Root} ATS node for a text note */
4
- export declare function createTextNoteATS(event: NostrEvent | EventTemplate | string, content?: string): Root;
4
+ export declare function createEventContentTree(event: NostrEvent | EventTemplate | string, content?: string): Root;
5
+ /** @deprecated use createEventContentTree instead */
6
+ export declare const createTextNoteATS: typeof createEventContentTree;
@@ -1,5 +1,5 @@
1
1
  /** Creates a {@link Root} ATS node for a text note */
2
- export function createTextNoteATS(event, content) {
2
+ export function createEventContentTree(event, content) {
3
3
  return {
4
4
  type: "root",
5
5
  event: typeof event !== "string" ? event : undefined,
@@ -11,3 +11,5 @@ export function createTextNoteATS(event, content) {
11
11
  ],
12
12
  };
13
13
  }
14
+ /** @deprecated use createEventContentTree instead */
15
+ export const createTextNoteATS = createEventContentTree;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "applesauce-content",
3
- "version": "1.0.0",
3
+ "version": "2.0.0",
4
4
  "description": "Unified plugins for processing event content",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -52,9 +52,9 @@
52
52
  "@types/hast": "^3.0.4",
53
53
  "@types/mdast": "^4.0.4",
54
54
  "@types/unist": "^3.0.3",
55
- "applesauce-core": "^1.0.0",
55
+ "applesauce-core": "^2.0.0",
56
56
  "mdast-util-find-and-replace": "^3.0.2",
57
- "nostr-tools": "^2.10.4",
57
+ "nostr-tools": "^2.13",
58
58
  "remark": "^15.0.1",
59
59
  "remark-parse": "^11.0.0",
60
60
  "unified": "^11.0.5",
@@ -62,7 +62,8 @@
62
62
  },
63
63
  "devDependencies": {
64
64
  "typescript": "^5.8.3",
65
- "vitest": "^3.1.1"
65
+ "applesauce-signers": "^2.0.0",
66
+ "vitest": "^3.2.3"
66
67
  },
67
68
  "funding": {
68
69
  "type": "lightning",