Browse Source

Add buttons to Compose view

master
buttercat1791 1 year ago
parent
commit
67ff783f7d
  1. 6
      src/lib/components/Navigation.svelte
  2. 24
      src/lib/components/Preview.svelte
  3. 43
      src/lib/parser.ts
  4. 19
      src/routes/new/edit/+page.svelte
  5. 14
      src/routes/new/review/+page.svelte

6
src/lib/components/Navigation.svelte

@ -19,9 +19,9 @@
<NavHamburger class='btn-leather' /> <NavHamburger class='btn-leather' />
</div> </div>
<NavUl class='ul-leather'> <NavUl class='ul-leather'>
<NavLi href='./about'>About</NavLi> <NavLi href='/about'>About</NavLi>
<NavLi href='./new/edit'>New Note</NavLi> <NavLi href='/new/edit'>New Note</NavLi>
<NavLi href='./visualize'>Visualize</NavLi> <NavLi href='/visualize'>Visualize</NavLi>
<NavLi> <NavLi>
<DarkMode btnClass='btn-leather p-0'/> <DarkMode btnClass='btn-leather p-0'/>
</NavLi> </NavLi>

24
src/lib/components/Preview.svelte

@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
import { parser } from "$lib/parser"; import { parser } from "$lib/parser";
import { Heading, P } from "flowbite-svelte"; import { Button, Heading, P, Tooltip } from "flowbite-svelte";
import { CaretDownSolid, CaretUpSolid, EditOutline } from "flowbite-svelte-icons";
export let sectionClass: string = ''; export let sectionClass: string = '';
@ -8,6 +9,7 @@
export let depth: number = 0; export let depth: number = 0;
export let allowEditing: boolean = false; export let allowEditing: boolean = false;
// TODO: Add editing functionality. // TODO: Add editing functionality.
const isEditing: boolean = false;
const title = $parser.getIndexTitle(rootIndexId); const title = $parser.getIndexTitle(rootIndexId);
const orderedChildren = $parser.getOrderedChildIds(rootIndexId); const orderedChildren = $parser.getOrderedChildIds(rootIndexId);
@ -35,11 +37,29 @@
<Heading tag={getHeadingTag(depth)} class='h-leather'>{title}</Heading> <Heading tag={getHeadingTag(depth)} class='h-leather'>{title}</Heading>
{#each orderedChildren as id, index} {#each orderedChildren as id, index}
{#if childIndices.includes(id)} {#if childIndices.includes(id)}
<svelte:self {$parser} rootIndexId={id} depth={depth + 1} /> <svelte:self rootIndexId={id} depth={depth + 1} {allowEditing} />
{:else if (childZettels.includes(id))} {:else if (childZettels.includes(id))}
<div class='grid grid-cols-[1fr_auto] gap-2'>
<P class='note-leather' firstupper={index === 0}> <P class='note-leather' firstupper={index === 0}>
{@html $parser.getContent(id)} {@html $parser.getContent(id)}
</P> </P>
{#if allowEditing}
<div class='flex flex-col space-y-2 justify-start'>
<Button class='btn-leather' size='sm' outline>
<CaretUpSolid />
</Button>
<Button class='btn-leather' size='sm' outline>
<CaretDownSolid />
</Button>
<Button class='btn-leather' size='sm' outline>
<EditOutline />
</Button>
<Tooltip class='tooltip-leather' type='auto' placement='top'>
Edit
</Tooltip>
</div>
{/if}
</div>
{/if} {/if}
{/each} {/each}
{:else} {:else}

43
src/lib/parser.ts

@ -167,7 +167,7 @@ export default class Pharos {
* @remarks The root index ID may be used to retrieve metadata or children from the root index. * @remarks The root index ID may be used to retrieve metadata or children from the root index.
*/ */
getRootIndexId(): string { getRootIndexId(): string {
return this.normalizeDTag(this.rootNodeId ?? ''); return this.normalizeId(this.rootNodeId) ?? '';
} }
/** /**
@ -309,6 +309,7 @@ export default class Pharos {
*/ */
private treeProcessor(treeProcessor: Extensions.TreeProcessor, document: Document) { private treeProcessor(treeProcessor: Extensions.TreeProcessor, document: Document) {
this.rootNodeId = this.generateNodeId(document); this.rootNodeId = this.generateNodeId(document);
document.setId(this.rootNodeId);
this.nodes.set(this.rootNodeId, document); this.nodes.set(this.rootNodeId, document);
this.eventToKindMap.set(this.rootNodeId, 30040); this.eventToKindMap.set(this.rootNodeId, 30040);
this.indexToChildEventsMap.set(this.rootNodeId, new Set<string>()); this.indexToChildEventsMap.set(this.rootNodeId, new Set<string>());
@ -339,7 +340,7 @@ export default class Pharos {
* @remarks Sections are mapped as kind 30040 indexToChildEventsMap by default. * @remarks Sections are mapped as kind 30040 indexToChildEventsMap by default.
*/ */
private processSection(section: Section): AbstractNode[] { private processSection(section: Section): AbstractNode[] {
let sectionId = section.getId(); let sectionId = this.normalizeId(section.getId());
if (!sectionId) { if (!sectionId) {
sectionId = this.generateNodeId(section); sectionId = this.generateNodeId(section);
} }
@ -353,7 +354,7 @@ export default class Pharos {
this.eventToKindMap.set(sectionId, 30040); // Sections are indexToChildEventsMap by default. this.eventToKindMap.set(sectionId, 30040); // Sections are indexToChildEventsMap by default.
this.indexToChildEventsMap.set(sectionId, new Set<string>()); this.indexToChildEventsMap.set(sectionId, new Set<string>());
const parentId = section.getParent()?.getId(); const parentId = this.normalizeId(section.getParent()?.getId());
if (!parentId) { if (!parentId) {
return []; return [];
} }
@ -376,7 +377,7 @@ export default class Pharos {
*/ */
private processBlock(block: Block): void { private processBlock(block: Block): void {
// Obtain or generate a unique ID for the block. // Obtain or generate a unique ID for the block.
let blockId = block.getId(); let blockId = this.normalizeId(block.getId());
if (!blockId) { if (!blockId) {
blockId = this.generateNodeId(block) ; blockId = this.generateNodeId(block) ;
block.setId(blockId); block.setId(blockId);
@ -390,7 +391,7 @@ export default class Pharos {
this.nodes.set(blockId, block); this.nodes.set(blockId, block);
this.eventToKindMap.set(blockId, 30041); // Blocks are zettels by default. this.eventToKindMap.set(blockId, 30041); // Blocks are zettels by default.
const parentId = block.getParent()?.getId(); const parentId = this.normalizeId(block.getParent()?.getId());
if (!parentId) { if (!parentId) {
return; return;
} }
@ -563,17 +564,17 @@ export default class Pharos {
// #region Utility Functions // #region Utility Functions
private generateNodeId(block: AbstractBlock): string { private generateNodeId(block: AbstractBlock): string {
let blockId: string = block.getId(); let blockId: string | null = this.normalizeId(block.getId());
if (blockId != null && blockId.length > 0) { if (blockId != null && blockId.length > 0) {
return blockId; return blockId;
} }
blockId = this.normalizeNodeId(block.getTitle() ?? ''); blockId = this.normalizeId(block.getTitle());
// Use the provided title, if possible. // Use the provided title, if possible.
if (blockId != null && blockId.length > 0) { if (blockId != null && blockId.length > 0) {
return this.normalizeNodeId(blockId); return blockId;
} }
const documentId = this.rootNodeId; const documentId = this.rootNodeId;
@ -754,23 +755,17 @@ export default class Pharos {
return blockId; return blockId;
} }
private normalizeNodeId(input: string): string { private normalizeId(input?: string): string | null {
return input if (input == null || input.length === 0) {
.toLowerCase() return null;
.replace(/\s+/g, '_') // Replace spaces with underscores.
.replace(/[^a-z0-9\_]/g, ''); // Remove non-alphanumeric characters except underscores.
} }
/** return he.decode(input)
* Normalizes a string to lower-kebab-case.
* @param input The string to normalize.
* @returns The normalized string.
*/
private normalizeDTag(input: string): string {
return input
.toLowerCase() .toLowerCase()
.replace(/[\s_]+/g, '-') // Replace spaces with hyphens. .replace(/[_]/g, ' ') // Replace underscores with spaces.
.replace(/[^a-z0-9\-]/g, ''); // Remove non-alphanumeric characters except hyphens. .trim()
.replace(/\s+/g, '-') // Replace spaces with dashes.
.replace(/[^a-z0-9\-]/g, ''); // Remove non-alphanumeric characters except dashes.
} }
private extractAndNormalizeWikilinks(content: string): string[][] { private extractAndNormalizeWikilinks(content: string): string[][] {
@ -781,8 +776,8 @@ export default class Pharos {
// TODO: Match custom-named wikilinks as defined in NIP-54. // TODO: Match custom-named wikilinks as defined in NIP-54.
while ((match = wikilinkPattern.exec(content)) !== null) { while ((match = wikilinkPattern.exec(content)) !== null) {
const linkName = match[1]; const linkName = match[1];
const normalizedText = this.normalizeDTag(linkName); const normalizedText = this.normalizeId(linkName);
wikilinks.push(['wikilink', normalizedText]); wikilinks.push(['wikilink', normalizedText!]);
} }
return wikilinks; return wikilinks;

19
src/routes/new/edit/+page.svelte

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { Button, Heading, Textarea, Toolbar, ToolbarButton, Tooltip } from "flowbite-svelte"; import { Heading, Textarea, Toolbar, ToolbarButton, Tooltip } from "flowbite-svelte";
import { CodeOutline, EyeSolid, PaperPlaneOutline } from "flowbite-svelte-icons"; import { CodeOutline, EyeSolid, PaperPlaneOutline } from "flowbite-svelte-icons";
import { editorText } from "$lib/stores"; import { editorText } from "$lib/stores";
import Preview from "$lib/components/Preview.svelte"; import Preview from "$lib/components/Preview.svelte";
@ -10,14 +10,13 @@
// TODO: Prompt user to sign in before editing. // TODO: Prompt user to sign in before editing.
let isEditing: boolean = true; let isEditing: boolean = true;
let rootIndexId: string;
$parser = new Pharos($ndk);
$: rootIndexId = $parser?.getRootIndexId();
const showPreview = () => { const showPreview = () => {
$parser ??= new Pharos($ndk);
$parser.reset(); $parser.reset();
$parser.parse($editorText); $parser.parse($editorText);
rootIndexId = $parser.getRootIndexId();
isEditing = false; isEditing = false;
}; };
@ -28,7 +27,7 @@
const prepareReview = () => { const prepareReview = () => {
$parser.reset(); $parser.reset();
$parser.parse($editorText); $parser.parse($editorText);
goto('/new/review'); goto('/new/compose');
} }
</script> </script>
@ -48,8 +47,8 @@
<ToolbarButton name='Preview' on:click={showPreview}> <ToolbarButton name='Preview' on:click={showPreview}>
<EyeSolid class='w-6 h-6' /> <EyeSolid class='w-6 h-6' />
</ToolbarButton> </ToolbarButton>
<ToolbarButton name='Review' slot='end'> <ToolbarButton name='Review' slot='end' on:click={prepareReview}>
<PaperPlaneOutline class='w=6 h-6 rotate-90' on:click={prepareReview} /> <PaperPlaneOutline class='w=6 h-6 rotate-90' />
</ToolbarButton> </ToolbarButton>
</Toolbar> </Toolbar>
</Textarea> </Textarea>
@ -60,8 +59,8 @@
<ToolbarButton name='Edit' on:click={hidePreview}> <ToolbarButton name='Edit' on:click={hidePreview}>
<CodeOutline class='w-6 h-6' /> <CodeOutline class='w-6 h-6' />
</ToolbarButton> </ToolbarButton>
<ToolbarButton name='Review' slot='end'> <ToolbarButton name='Review' slot='end' on:click={prepareReview}>
<PaperPlaneOutline class='w=6 h-6 rotate-90' on:click={prepareReview} /> <PaperPlaneOutline class='w=6 h-6 rotate-90' />
</ToolbarButton> </ToolbarButton>
</Toolbar> </Toolbar>
{#if rootIndexId} {#if rootIndexId}

14
src/routes/new/review/+page.svelte

@ -1,14 +0,0 @@
<script lang='ts'>
import Preview from "$lib/components/Preview.svelte";
import { parser } from "$lib/parser";
import { Heading } from "flowbite-svelte";
</script>
<div class='w-full flex justify-center'>
<main class='main-leather flex flex-col space-y-4 max-w-2xl w-full mt-4 mb-4'>
<Heading tag='h1' class='h-leather mb-2'>Review</Heading>
<Preview rootIndexId={$parser.getRootIndexId()} allowEditing={true} />
</main>
</div>
Loading…
Cancel
Save