applesauce-content 5.0.0 → 6.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.
@@ -0,0 +1,9 @@
1
+ import { ParsedBlossomURI } from "applesauce-common/helpers/blossom";
2
+ import { Link, Nodes } from "mdast";
3
+ import { Transformer } from "unified";
4
+ export interface BlossomMdastLink extends Link {
5
+ type: "link";
6
+ data: ParsedBlossomURI;
7
+ }
8
+ /** Finds and creates BUD-10 `blossom:` URI links in a mdast tree */
9
+ export declare function remarkBlossomURIs(): Transformer<Nodes>;
@@ -0,0 +1,22 @@
1
+ import { parseBlossomURI } from "applesauce-common/helpers/blossom";
2
+ import { Tokens } from "applesauce-core/helpers/regexp";
3
+ import { findAndReplace } from "mdast-util-find-and-replace";
4
+ /** Finds and creates BUD-10 `blossom:` URI links in a mdast tree */
5
+ export function remarkBlossomURIs() {
6
+ return (tree) => {
7
+ findAndReplace(tree, [
8
+ Tokens.blossom,
9
+ (raw) => {
10
+ const parsed = parseBlossomURI(raw);
11
+ if (!parsed)
12
+ return false;
13
+ return {
14
+ type: "link",
15
+ data: parsed,
16
+ url: raw,
17
+ children: [{ type: "text", value: raw }],
18
+ };
19
+ },
20
+ ]);
21
+ };
22
+ }
@@ -1 +1,2 @@
1
1
  export * from "./mentions.js";
2
+ export * from "./blossom.js";
@@ -1 +1,2 @@
1
1
  export * from "./mentions.js";
2
+ export * from "./blossom.js";
@@ -13,6 +13,9 @@ export function truncateContent(tree, maxLength = 256) {
13
13
  case "cashu":
14
14
  length += node.raw.length;
15
15
  break;
16
+ case "blossom":
17
+ length += node.raw.length;
18
+ break;
16
19
  case "gallery":
17
20
  length += node.links.reduce((t, l) => t + l.length, 0);
18
21
  break;
@@ -53,6 +53,21 @@ export interface Emoji extends Node {
53
53
  url: string;
54
54
  tag: ["emoji", ...string[]];
55
55
  }
56
+ export interface BlossomURI extends Node {
57
+ type: "blossom";
58
+ /** The original matched text, e.g. `blossom:<hash>.pdf?xs=...` */
59
+ raw: string;
60
+ /** 64 character lowercase hex sha256 hash of the blob */
61
+ sha256: string;
62
+ /** File extension without the leading dot */
63
+ ext: string;
64
+ /** Optional exact blob size in bytes */
65
+ size?: number;
66
+ /** Server hints from repeated `xs` query parameters */
67
+ servers: string[];
68
+ /** Author hex pubkeys from repeated `as` query parameters */
69
+ authors: string[];
70
+ }
56
71
  export interface ContentMap {
57
72
  text: Text;
58
73
  link: Link;
@@ -62,6 +77,7 @@ export interface ContentMap {
62
77
  hashtag: Hashtag;
63
78
  emoji: Emoji;
64
79
  gallery: Gallery;
80
+ blossom: BlossomURI;
65
81
  }
66
82
  export type Content = ContentMap[keyof ContentMap];
67
83
  export interface Root extends Parent {
@@ -0,0 +1,4 @@
1
+ import { Transformer } from "unified";
2
+ import { Root } from "../nast/types.js";
3
+ /** Finds and creates BUD-10 blossom URI nodes in the tree */
4
+ export declare function blossomURIs(): Transformer<Root>;
@@ -0,0 +1,23 @@
1
+ import { parseBlossomURI } from "applesauce-common/helpers/blossom";
2
+ import { Tokens } from "applesauce-core/helpers/regexp";
3
+ import { findAndReplace } from "../nast/find-and-replace.js";
4
+ /** Finds and creates BUD-10 blossom URI nodes in the tree */
5
+ export function blossomURIs() {
6
+ return (tree) => {
7
+ findAndReplace(tree, [
8
+ [
9
+ Tokens.blossom,
10
+ (raw) => {
11
+ const parsed = parseBlossomURI(raw);
12
+ if (!parsed)
13
+ return false;
14
+ return {
15
+ type: "blossom",
16
+ raw,
17
+ ...parsed,
18
+ };
19
+ },
20
+ ],
21
+ ]);
22
+ };
23
+ }
@@ -9,9 +9,11 @@ import { galleries } from "./gallery.js";
9
9
  import { lightningInvoices } from "./lightning.js";
10
10
  import { eolMetadata } from "../nast/eol-metadata.js";
11
11
  import { links } from "./links.js";
12
+ import { blossomURIs } from "./blossom.js";
12
13
  export const TextNoteContentSymbol = Symbol.for("text-note-content");
13
14
  // default kind 1 transformers
14
15
  export const textNoteTransformers = [
16
+ blossomURIs,
15
17
  links,
16
18
  nostrMentions,
17
19
  galleries,
@@ -1,4 +1,8 @@
1
1
  import { Transformer } from "unified";
2
2
  import { Root } from "../nast/types.js";
3
+ export interface GalleriesOptions {
4
+ /** When true, adjacent `blossom:` image URIs are clustered alongside HTTP image links. Defaults to false. */
5
+ includeBlossom?: boolean;
6
+ }
3
7
  /** Group images into galleries in an ATS tree */
4
- export declare function galleries(types?: string[]): Transformer<Root>;
8
+ export declare function galleries(types?: string[], options?: GalleriesOptions): Transformer<Root>;
@@ -1,21 +1,23 @@
1
1
  import { convertToUrl, getURLFilename, IMAGE_EXT } from "applesauce-core/helpers/url";
2
2
  /** Group images into galleries in an ATS tree */
3
- export function galleries(types = IMAGE_EXT) {
3
+ export function galleries(types = IMAGE_EXT, options = {}) {
4
+ const { includeBlossom = false } = options;
4
5
  return (tree) => {
5
- let links = [];
6
+ let items = [];
7
+ const getItemHref = (item) => (item.type === "link" ? item.href : item.raw);
6
8
  const commit = (index) => {
7
9
  // only create a gallery if there are more than a single image
8
- if (links.length > 1) {
9
- const start = tree.children.indexOf(links[0]);
10
- const end = tree.children.indexOf(links[links.length - 1]);
10
+ if (items.length > 1) {
11
+ const start = tree.children.indexOf(items[0]);
12
+ const end = tree.children.indexOf(items[items.length - 1]);
11
13
  // replace all nodes with a gallery
12
- tree.children.splice(start, 1 + end - start, { type: "gallery", links: links.map((l) => l.href) });
13
- links = [];
14
+ tree.children.splice(start, 1 + end - start, { type: "gallery", links: items.map(getItemHref) });
15
+ items = [];
14
16
  // return new cursor
15
17
  return end - 1;
16
18
  }
17
19
  else {
18
- links = [];
20
+ items = [];
19
21
  return index;
20
22
  }
21
23
  };
@@ -26,13 +28,21 @@ export function galleries(types = IMAGE_EXT) {
26
28
  const url = convertToUrl(node.href);
27
29
  const filename = getURLFilename(url);
28
30
  if (filename && types.some((ext) => filename.endsWith(ext))) {
29
- links.push(node);
31
+ items.push(node);
30
32
  }
31
33
  else {
32
34
  i = commit(i);
33
35
  }
34
36
  }
35
- else if (node.type === "text" && links.length > 0) {
37
+ else if (node.type === "blossom" && includeBlossom) {
38
+ if (types.some((ext) => ext === `.${node.ext.toLowerCase()}`)) {
39
+ items.push(node);
40
+ }
41
+ else {
42
+ i = commit(i);
43
+ }
44
+ }
45
+ else if (node.type === "text" && items.length > 0) {
36
46
  const isEmpty = node.value === "\n" || !node.value.match(/[^\s]/g);
37
47
  if (!isEmpty)
38
48
  i = commit(i);
@@ -7,3 +7,4 @@ export * from "./parser.js";
7
7
  export * from "./hashtag.js";
8
8
  export * from "./gallery.js";
9
9
  export * from "./lightning.js";
10
+ export * from "./blossom.js";
@@ -7,3 +7,4 @@ export * from "./parser.js";
7
7
  export * from "./hashtag.js";
8
8
  export * from "./gallery.js";
9
9
  export * from "./lightning.js";
10
+ export * from "./blossom.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "applesauce-content",
3
- "version": "5.0.0",
3
+ "version": "6.0.0",
4
4
  "description": "Unified plugins for processing event content",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -50,8 +50,8 @@
50
50
  "@types/hast": "^3.0.4",
51
51
  "@types/mdast": "^4.0.4",
52
52
  "@types/unist": "^3.0.3",
53
- "applesauce-common": "^5.0.0",
54
- "applesauce-core": "^5.0.0",
53
+ "applesauce-common": "^6.0.0",
54
+ "applesauce-core": "^6.0.0",
55
55
  "mdast-util-find-and-replace": "^3.0.2",
56
56
  "remark": "^15.0.1",
57
57
  "remark-parse": "^11.0.0",
@@ -59,7 +59,7 @@
59
59
  "unist-util-visit-parents": "^6.0.1"
60
60
  },
61
61
  "devDependencies": {
62
- "applesauce-signers": "^5.0.0",
62
+ "applesauce-signers": "^6.0.0",
63
63
  "rimraf": "^6.0.1",
64
64
  "typescript": "^5.8.3",
65
65
  "vitest": "^4.0.15"