From 00ea4492983d57262267402b39bd91f36f6adfc6 Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Thu, 25 Jan 2024 00:00:00 +0000 Subject: [PATCH] feat(PRPage): parse event content with line breaks This applies a really basic version of the parsing in ndk-svelte-components which was copied from coracle. hopefully they can be fully aligned in the future. I applied extra typing and will intergrate other ParsedParts when needed. applied line breaks to commit messages, pr description and default for event content. --- package.json | 4 +- .../components/events/content/Kind317.svelte | 3 +- .../events/content/ParsedContent.svelte | 21 ++++ src/lib/components/events/content/utils.ts | 96 +++++++++++++++++++ src/lib/wrappers/EventCard.svelte | 3 +- .../repo/[repo_id]/pr/[pr_id]/+page.svelte | 5 +- yarn.lock | 21 +++- 7 files changed, 148 insertions(+), 5 deletions(-) create mode 100644 src/lib/components/events/content/ParsedContent.svelte create mode 100644 src/lib/components/events/content/utils.ts diff --git a/package.json b/package.json index bb30564..1cb5722 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "@tailwindcss/typography": "^0.5.10", "@types/jest-image-snapshot": "^6.2.1", "@types/node": "^20.8.2", + "@types/ramda": "^0.29.10", "autoprefixer": "^10.4.16", "concurrently": "^8.2.2", "http-server": "^14.1.1", @@ -53,7 +54,8 @@ "@nostr-dev-kit/ndk-svelte-components": "^1.3.0", "daisyui": "^4.4", "dayjs": "^1.11.10", - "parse-diff": "^0.11.1" + "parse-diff": "^0.11.1", + "ramda": "^0.29.1" }, "resolutions": { "jackspeak": "2.1.1" diff --git a/src/lib/components/events/content/Kind317.svelte b/src/lib/components/events/content/Kind317.svelte index f49a950..4f86c73 100644 --- a/src/lib/components/events/content/Kind317.svelte +++ b/src/lib/components/events/content/Kind317.svelte @@ -1,6 +1,7 @@ + +
+ {#each fullContent as part, i} + {#if isParsedNewLine(part)} + {#if part.value.length > 1} +
+ {/if} +
+ {:else if isParsedText(part)} + {part.value} + {/if} + {/each} +
diff --git a/src/lib/components/events/content/utils.ts b/src/lib/components/events/content/utils.ts new file mode 100644 index 0000000..bc8f2b6 --- /dev/null +++ b/src/lib/components/events/content/utils.ts @@ -0,0 +1,96 @@ +import type { NDKTag } from "@nostr-dev-kit/ndk"; +import { nip19 } from "nostr-tools"; +import { identity, last, pluck } from "ramda"; + +export const TOPIC = "topic"; +export const LINK = "link"; +export const LINKCOLLECTION = "link[]"; +export const HTML = "html"; +export const INVOICE = "invoice"; +export const NOSTR_NOTE = "nostr:note"; +export const NOSTR_NEVENT = "nostr:nevent"; +export const NOSTR_NPUB = "nostr:npub"; +export const NOSTR_NPROFILE = "nostr:nprofile"; +export const NOSTR_NADDR = "nostr:naddr"; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const first = (list: any) => (list ? list[0] : undefined); + +export const fromNostrURI = (s: string) => s.replace(/^[\w+]+:\/?\/?/, ""); + +export const urlIsMedia = (url: string) => + !url.match(/\.(apk|docx|xlsx|csv|dmg)/) && last(url.split("://"))?.includes("/"); + +export type ContentArgs = { + content: string; + tags?: Array; +}; + +export type ParsedPart = ParsedNewLine | ParsedText; + +export const NEWLINE = "newline"; + +export type ParsedNewLine = { + type: "newline", + value: string, +}; + +export const isParsedNewLine = (part: ParsedPart): part is ParsedNewLine => { + return part.type == "newline" +}; + +export const TEXT = "text"; + +export type ParsedText = { + type: "text", + value: string, +}; + +export const isParsedText = (part: ParsedPart): part is ParsedText => { + return part.type == "text" +}; + +export const parseContent = ({ content, tags = [] }: ContentArgs): ParsedPart[] => { + const result: ParsedPart[] = []; + let text = content.trim(); + let buffer = ""; + + const parseNewline = () => { + const newline = first(text.match(/^\n+/)); + + if (newline) { + return [NEWLINE, newline, newline]; + } + }; + + while (text) { + // The order that this runs matters + const part = + parseNewline(); + + if (part) { + if (buffer) { + result.push({ type: "text", value: buffer }); + buffer = ""; + } + + const [type, raw, value] = part; + + result.push({ type, value }); + text = text.slice(raw.length); + } else { + // Instead of going character by character and re-running all the above regular expressions + // a million times, try to match the next word and add it to the buffer + const match = first(text.match(/^[\w\d]+ ?/i)) || text[0]; + + buffer += match; + text = text.slice(match.length); + } + } + + if (buffer) { + result.push({ type: TEXT, value: buffer }); + } + + return result; +}; diff --git a/src/lib/wrappers/EventCard.svelte b/src/lib/wrappers/EventCard.svelte index b83057b..5a64c8d 100644 --- a/src/lib/wrappers/EventCard.svelte +++ b/src/lib/wrappers/EventCard.svelte @@ -2,6 +2,7 @@ import EventWrapper from "$lib/components/events/EventWrapper.svelte"; import Kind19851985 from "$lib/components/events/content/Kind19851985.svelte"; import Kind317 from "$lib/components/events/content/Kind317.svelte"; + import ParsedContent from "$lib/components/events/content/ParsedContent.svelte"; import type { User } from "$lib/components/users/type"; import { defaults as user_defaults } from "$lib/components/users/type"; import { patch_kind, pr_status_kind } from "$lib/kinds"; @@ -27,6 +28,6 @@ {:else if event.kind === pr_status_kind} {:else} - {event.content} + {/if} diff --git a/src/routes/repo/[repo_id]/pr/[pr_id]/+page.svelte b/src/routes/repo/[repo_id]/pr/[pr_id]/+page.svelte index e7efdd8..75e20be 100644 --- a/src/routes/repo/[repo_id]/pr/[pr_id]/+page.svelte +++ b/src/routes/repo/[repo_id]/pr/[pr_id]/+page.svelte @@ -10,6 +10,7 @@ import Thread from "$lib/wrappers/Thread.svelte"; import PrDetails from "$lib/components/prs/PRDetails.svelte"; import Container from "$lib/components/Container.svelte"; + import ParsedContent from "$lib/components/events/content/ParsedContent.svelte"; export let data: { repo_id: string; @@ -63,7 +64,9 @@
- {$selected_pr_full.summary.descritpion} +