Browse Source

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.
master
DanConwayDev 2 years ago
parent
commit
00ea449298
No known key found for this signature in database
GPG Key ID: 68E15486D73F75E1
  1. 4
      package.json
  2. 3
      src/lib/components/events/content/Kind317.svelte
  3. 21
      src/lib/components/events/content/ParsedContent.svelte
  4. 96
      src/lib/components/events/content/utils.ts
  5. 3
      src/lib/wrappers/EventCard.svelte
  6. 5
      src/routes/repo/[repo_id]/pr/[pr_id]/+page.svelte
  7. 21
      yarn.lock

4
package.json

@ -31,6 +31,7 @@
"@tailwindcss/typography": "^0.5.10", "@tailwindcss/typography": "^0.5.10",
"@types/jest-image-snapshot": "^6.2.1", "@types/jest-image-snapshot": "^6.2.1",
"@types/node": "^20.8.2", "@types/node": "^20.8.2",
"@types/ramda": "^0.29.10",
"autoprefixer": "^10.4.16", "autoprefixer": "^10.4.16",
"concurrently": "^8.2.2", "concurrently": "^8.2.2",
"http-server": "^14.1.1", "http-server": "^14.1.1",
@ -53,7 +54,8 @@
"@nostr-dev-kit/ndk-svelte-components": "^1.3.0", "@nostr-dev-kit/ndk-svelte-components": "^1.3.0",
"daisyui": "^4.4", "daisyui": "^4.4",
"dayjs": "^1.11.10", "dayjs": "^1.11.10",
"parse-diff": "^0.11.1" "parse-diff": "^0.11.1",
"ramda": "^0.29.1"
}, },
"resolutions": { "resolutions": {
"jackspeak": "2.1.1" "jackspeak": "2.1.1"

3
src/lib/components/events/content/Kind317.svelte

@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
import type { NDKTag } from "@nostr-dev-kit/ndk"; import type { NDKTag } from "@nostr-dev-kit/ndk";
import parseDiff from "parse-diff"; import parseDiff from "parse-diff";
import ParsedContent from "./ParsedContent.svelte";
export let content: string = ""; export let content: string = "";
export let tags: NDKTag[] = []; export let tags: NDKTag[] = [];
@ -19,7 +20,7 @@
<div class=""> <div class="">
<div class="bg-base-300 rounded-t p-1 flex"> <div class="bg-base-300 rounded-t p-1 flex">
<article class="ml-2 prose font-mono flex-grow"> <article class="ml-2 prose font-mono flex-grow">
{commit_message} <ParsedContent content={commit_message} />
</article> </article>
<div class="text-xs text-neutral p-1 flex-none align-middle"> <div class="text-xs text-neutral p-1 flex-none align-middle">
commit commit

21
src/lib/components/events/content/ParsedContent.svelte

@ -0,0 +1,21 @@
<script lang="ts">
import type { NDKTag } from "@nostr-dev-kit/ndk";
import { isParsedNewLine, isParsedText, parseContent } from "./utils";
export let content: string = "";
export let tags: NDKTag[] = [];
const fullContent = parseContent({ content, tags });
</script>
<div>
{#each fullContent as part, i}
{#if isParsedNewLine(part)}
{#if part.value.length > 1}
<br />
{/if}
<br />
{:else if isParsedText(part)}
{part.value}
{/if}
{/each}
</div>

96
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<NDKTag>;
};
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;
};

3
src/lib/wrappers/EventCard.svelte

@ -2,6 +2,7 @@
import EventWrapper from "$lib/components/events/EventWrapper.svelte"; import EventWrapper from "$lib/components/events/EventWrapper.svelte";
import Kind19851985 from "$lib/components/events/content/Kind19851985.svelte"; import Kind19851985 from "$lib/components/events/content/Kind19851985.svelte";
import Kind317 from "$lib/components/events/content/Kind317.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 type { User } from "$lib/components/users/type";
import { defaults as user_defaults } from "$lib/components/users/type"; import { defaults as user_defaults } from "$lib/components/users/type";
import { patch_kind, pr_status_kind } from "$lib/kinds"; import { patch_kind, pr_status_kind } from "$lib/kinds";
@ -27,6 +28,6 @@
{:else if event.kind === pr_status_kind} {:else if event.kind === pr_status_kind}
<Kind19851985 tags={event.tags} /> <Kind19851985 tags={event.tags} />
{:else} {:else}
{event.content} <ParsedContent content={event.content} tags={event.tags} />
{/if} {/if}
</EventWrapper> </EventWrapper>

5
src/routes/repo/[repo_id]/pr/[pr_id]/+page.svelte

@ -10,6 +10,7 @@
import Thread from "$lib/wrappers/Thread.svelte"; import Thread from "$lib/wrappers/Thread.svelte";
import PrDetails from "$lib/components/prs/PRDetails.svelte"; import PrDetails from "$lib/components/prs/PRDetails.svelte";
import Container from "$lib/components/Container.svelte"; import Container from "$lib/components/Container.svelte";
import ParsedContent from "$lib/components/events/content/ParsedContent.svelte";
export let data: { export let data: {
repo_id: string; repo_id: string;
@ -63,7 +64,9 @@
<div class="md:flex"> <div class="md:flex">
<div class="md:w-2/3 md:mr-2"> <div class="md:w-2/3 md:mr-2">
<div class="prose my-3"> <div class="prose my-3">
{$selected_pr_full.summary.descritpion} <ParsedContent
content={$selected_pr_full.summary.descritpion}
/>
</div> </div>
<div role="alert" class="alert"> <div role="alert" class="alert">
<svg <svg

21
yarn.lock

@ -3341,6 +3341,13 @@
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.10.tgz#0af26845b5067e1c9a622658a51f60a3934d51e8" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.10.tgz#0af26845b5067e1c9a622658a51f60a3934d51e8"
integrity sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw== integrity sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==
"@types/ramda@^0.29.10":
version "0.29.10"
resolved "https://registry.yarnpkg.com/@types/ramda/-/ramda-0.29.10.tgz#2584b268f9e0dd71ed4e5432b095186eb24a1f8f"
integrity sha512-0BzWVKtSEtignlk+XBuK88Il5wzQwbRVfEkzE8iKm02NYHMGQ/9ffB05M+zXhTCqo50DOIAT9pNSJsjFMMG4rQ==
dependencies:
types-ramda "^0.29.7"
"@types/range-parser@*": "@types/range-parser@*":
version "1.2.7" version "1.2.7"
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb"
@ -8234,7 +8241,7 @@ ramda@0.29.0:
resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.29.0.tgz#fbbb67a740a754c8a4cbb41e2a6e0eb8507f55fb" resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.29.0.tgz#fbbb67a740a754c8a4cbb41e2a6e0eb8507f55fb"
integrity sha512-BBea6L67bYLtdbOqfp8f58fPMqEwx0doL+pAi8TZyp2YWz8R9G8z9x75CZI8W+ftqhFHCpEX2cRnUUXK130iKA== integrity sha512-BBea6L67bYLtdbOqfp8f58fPMqEwx0doL+pAi8TZyp2YWz8R9G8z9x75CZI8W+ftqhFHCpEX2cRnUUXK130iKA==
ramda@^0.29.0: ramda@^0.29.0, ramda@^0.29.1:
version "0.29.1" version "0.29.1"
resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.29.1.tgz#408a6165b9555b7ba2fc62555804b6c5a2eca196" resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.29.1.tgz#408a6165b9555b7ba2fc62555804b6c5a2eca196"
integrity sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA== integrity sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==
@ -9330,6 +9337,11 @@ ts-interface-checker@^0.1.9:
resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699"
integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==
ts-toolbelt@^9.6.0:
version "9.6.0"
resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz#50a25426cfed500d4a09bd1b3afb6f28879edfd5"
integrity sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==
tslib@^1.13.0: tslib@^1.13.0:
version "1.14.1" version "1.14.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
@ -9422,6 +9434,13 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==
types-ramda@^0.29.7:
version "0.29.7"
resolved "https://registry.yarnpkg.com/types-ramda/-/types-ramda-0.29.7.tgz#dbd0dfc3c032502da2824b6f060f9b68bddffddc"
integrity sha512-8KBxZGJwUF3MpRkkJauSpvfHXk8Ssq15QXGuCBTDGeKd9PfheokkC3wAKRV3djej9O31Qa5M7Owsg8hF0GjtAw==
dependencies:
ts-toolbelt "^9.6.0"
typescript-lru-cache@^2.0.0: typescript-lru-cache@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/typescript-lru-cache/-/typescript-lru-cache-2.0.0.tgz#d4ad0f071ab51987b088a57c3c502d7dd62dee07" resolved "https://registry.yarnpkg.com/typescript-lru-cache/-/typescript-lru-cache-2.0.0.tgz#d4ad0f071ab51987b088a57c3c502d7dd62dee07"

Loading…
Cancel
Save