diff --git a/src/lib/components/Preview.svelte b/src/lib/components/Preview.svelte
index d74d021..0b804d2 100644
--- a/src/lib/components/Preview.svelte
+++ b/src/lib/components/Preview.svelte
@@ -1,10 +1,43 @@
-
+ {#if depth < 4}
+ {title}
+ {#each orderedChildren as id}
+ {#if childIndices.includes(id)}
+
+ {:else if (childZettels.includes(id))}
+ {@html parser.getHtmlContent(id)}
+ {/if}
+ {/each}
+ {:else}
+ {@html parser.getHtmlContent(rootIndexId)}
+ {/if}
\ No newline at end of file
diff --git a/src/lib/parser.ts b/src/lib/parser.ts
index bcabac0..4fca9bd 100644
--- a/src/lib/parser.ts
+++ b/src/lib/parser.ts
@@ -1,5 +1,5 @@
import NDK, { NDKEvent } from '@nostr-dev-kit/ndk';
-import {
+import asciidoctor, {
AbstractBlock,
AbstractNode,
Asciidoctor,
@@ -28,7 +28,7 @@ interface IndexMetadata {
* @class
* @augments Asciidoctor
*/
-export default class Pharos extends Asciidoctor {
+export default class Pharos {
/**
* Key to terminology used in the class:
*
@@ -50,8 +50,12 @@ export default class Pharos extends Asciidoctor {
* hierarchically to form the Abstract Syntax Tree (AST) representation of the document.
*/
+ private asciidoctor: Asciidoctor;
+
private ndk: NDK;
+ private blockCounter: number = 0;
+
/**
* The HTML content of the converted document.
*/
@@ -95,12 +99,12 @@ export default class Pharos extends Asciidoctor {
// #region Public API
constructor(ndk: NDK) {
- super();
+ this.asciidoctor = asciidoctor();
this.ndk = ndk;
const pharos = this;
- this.Extensions.register(function () {
+ this.asciidoctor.Extensions.register(function () {
const registry = this;
registry.treeProcessor(function () {
const dsl = this;
@@ -113,7 +117,7 @@ export default class Pharos extends Asciidoctor {
}
parse(content: string, options?: ProcessorOptions | undefined): void {
- this.html = this.convert(content, options) as string | Document | undefined;
+ this.html = this.asciidoctor.convert(content, options) as string | Document | undefined;
}
getEvents(pubkey: string): NDKEvent[] {
@@ -134,7 +138,7 @@ export default class Pharos extends Asciidoctor {
* @remarks The root index ID may be used to retrieve metadata or children from the root index.
*/
getRootIndexId(): string {
- return this.rootIndexId!;
+ return this.rootNodeId!;
}
/**
@@ -162,9 +166,16 @@ export default class Pharos extends Asciidoctor {
}
/**
- * @returns The converted content of the zettel with the given ID.
+ * @returns The IDs of any child nodes in the order in which they should be rendered.
*/
- getZettelHtml(id: string): string {
+ getOrderedChildIds(id: string): string[] {
+ return Array.from(this.indexToChildEventsMap.get(id)!);
+ }
+
+ /**
+ * @returns The converted content of the node with the given ID.
+ */
+ getHtmlContent(id: string): string {
const block = this.nodes.get(id) as Block;
return block.convert();
}
@@ -181,6 +192,11 @@ export default class Pharos extends Asciidoctor {
*/
private treeProcessor(treeProcessor: Extensions.TreeProcessor, document: Document) {
this.rootNodeId = document.getId();
+ if (!this.rootNodeId) {
+ this.rootNodeId = this.normalizeNodeId(document.getTitle() ?? 'root');
+ document.setId(this.rootNodeId);
+ }
+
this.nodes.set(this.rootNodeId, document);
this.eventToKindMap.set(this.rootNodeId, 30040);
this.indexToChildEventsMap.set(this.rootNodeId, new Set());
@@ -194,8 +210,8 @@ export default class Pharos extends Asciidoctor {
continue;
}
- if (block instanceof Section) {
- const children = this.processSection(block);
+ if (block.getContext() === 'section') {
+ const children = this.processSection(block as Section);
nodeQueue.push(...children);
} else {
this.processBlock(block as Block);
@@ -211,7 +227,10 @@ export default class Pharos extends Asciidoctor {
* @remarks Sections are mapped as kind 30040 indexToChildEventsMap by default.
*/
private processSection(section: Section): AbstractNode[] {
- const sectionId = section.getId();
+ let sectionId = section.getId();
+ if (!sectionId) {
+ sectionId = this.normalizeNodeId(section.getTitle() ?? `${section.getContext()}_${this.blockCounter++}`);
+ }
// Prevent duplicates.
if (this.nodes.has(sectionId)) {
@@ -244,7 +263,12 @@ export default class Pharos extends Asciidoctor {
* @remarks Blocks are mapped as kind 30041 zettels by default.
*/
private processBlock(block: Block): void {
- const blockId = block.getId();
+ // Obtain or generate a unique ID for the block.
+ let blockId = block.getId();
+ if (!blockId) {
+ blockId = `${this.normalizeNodeId(block.getContext())}_${this.blockCounter++}`;
+ block.setId(blockId);
+ }
// Prevent duplicates.
if (this.nodes.has(blockId)) {
@@ -426,6 +450,13 @@ export default class Pharos extends Asciidoctor {
// #region Utility Functions
+ private normalizeNodeId(input: string): string {
+ return input
+ .toLowerCase()
+ .replace(/\s+/g, '_') // Replace spaces with underscores.
+ .replace(/[^a-z0-9\_]/g, ''); // Remove non-alphanumeric characters except underscores.
+ }
+
/**
* Normalizes a string to lower-kebab-case.
* @param input The string to normalize.
diff --git a/src/routes/new/edit/+page.svelte b/src/routes/new/edit/+page.svelte
index bd40ab8..0d672ba 100644
--- a/src/routes/new/edit/+page.svelte
+++ b/src/routes/new/edit/+page.svelte
@@ -6,13 +6,15 @@
import Pharos from "$lib/parser";
import { ndk } from "$lib/ndk";
- const parser: Pharos = new Pharos($ndk);
-
+ let parser: Pharos;
let isEditing: boolean = true;
+ $: rootIndexId = parser?.getRootIndexId();
+
const showPreview = () => {
- isEditing = false;
+ parser = new Pharos($ndk);
parser.parse($editorText);
+ isEditing = false;
};
const hidePreview = () => {
@@ -51,7 +53,9 @@
-
+ {#if rootIndexId}
+
+ {/if}
{/if}