Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions app/App.svelte
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<script lang="ts">


import { EditorView } from 'prosemirror-view';
import { Editor } from '../src/lib';
import { Base } from '@hyvor/design/components';
Expand Down Expand Up @@ -42,6 +44,18 @@
return {
src
};
},
bookmarkGetter: async () => {
if (!confirm('Simulate an bookmark?')) {
return null;
}

return {
url: 'https://www.google.com',
title: 'Google',
description: 'Google is a search engine',
image: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR28Yb6U3AlNA5vIusLWEahuo87-kpKkkZefA&s'
};
}
}}
/>
Expand Down
9 changes: 9 additions & 0 deletions src/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export interface Config {
// Bookmark block
// default: true
bookmarkEnabled: boolean;
bookmarkGetter?: (url: string) => Promise<BookmarkResult | null>;

// TOC: Table of Contents
// default: true
Expand Down Expand Up @@ -61,6 +62,7 @@ export const defaultConfig: Config = {
audioEnabled: true,
audioUploader: undefined,
bookmarkEnabled: true,
bookmarkGetter: undefined,
tocEnabled: true,
tableEnabled: true,
buttonEnabled: true,
Expand All @@ -74,4 +76,11 @@ export interface ImageUploadResult {

export interface AudioUploadResult {
src: string;
}

export interface BookmarkResult {
url: string;
title?: string;
description?: string;
image?: string;
}
9 changes: 9 additions & 0 deletions src/lib/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,13 @@ export function appendHtml(view: EditorView, html: string) {
view.dispatch(tr);
view.focus();

}

export function isValidUrl(url: string) {
try {
new URL(url);
return true;
} catch (e) {
return false;
}
}
22 changes: 22 additions & 0 deletions src/lib/nodeviews/bookmark/bookmark-create.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { BookmarkResult, Config } from "$lib/config";
import { type Schema } from "prosemirror-model";

export async function createBookmarkGetFigureNode(schema: Schema, bookmarkGetter: Config['bookmarkGetter']) {

const bookmark = await bookmarkGetter();

if (bookmark === null) {
return null;
}

return getFigureNode(schema, bookmark);
}

export function getFigureNode(schema: Schema, result: BookmarkResult) {
return schema.nodes.figure.create({}, [
schema.nodes.bookmark.create({
url: result.url
}),
schema.nodes.figcaption.create()
]);
}
12 changes: 6 additions & 6 deletions src/lib/plugins/slash/Bookmark/BookmarkCreator.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,18 @@
import { onMount } from "svelte";
import IconArrowReturnLeft from "@hyvor/icons/IconArrowReturnLeft";
import BookmarkDisplay from "./BookmarkDisplay.svelte";
import { isValidUrl } from "../../../helpers";

let show = $state(true);

interface Props {
url?: string;
onclose: () => void;
oncreate: (url: string) => void;
bookmarkGetter: (url: string) => Promise<{url: string, title?: string, description?: string, image?: string} | null>;
}

let { url = $bindable(""), onclose, oncreate }: Props = $props();
let { url = $bindable(""), onclose, oncreate, bookmarkGetter }: Props = $props();

let inputEl: HTMLInputElement | undefined = $state();
let inputStarted = $state(false);
Expand All @@ -35,9 +37,7 @@
let urlData: null | any = $state(null);

function handleFetch() {
return;

/* if (!inputStarted) {
if (!inputStarted) {
return;
}

Expand All @@ -58,7 +58,7 @@

isFetching = true;

getUnfold(url, "link")
bookmarkGetter(url)
.then((data) => {
urlData = data;
})
Expand All @@ -67,7 +67,7 @@
})
.finally(() => {
isFetching = false;
}); */
});
}

function handleCreate() {
Expand Down
94 changes: 52 additions & 42 deletions src/lib/plugins/slash/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import type { EditorView } from 'prosemirror-view';
import IconHandIndexThumb from '@hyvor/icons/IconHandIndexThumb';
import { uploadImageGetFigureNode } from '../../nodeviews/image/image-upload'
import { uploadAudioGetAudioNode } from '../../nodeviews/audio/audio-upload';
import { createBookmarkGetFigureNode } from '../../nodeviews/bookmark/bookmark-create';

export interface SlashOption {
name: string;
Expand Down Expand Up @@ -140,7 +141,9 @@ export function getOptions(view: EditorView, config: Config): SlashOption[] {
description: 'Link preview as a bookmark',
icon: IconBookmark,
keywords: ['bookmark', 'link'],
node: () => null // TODO:
node: () => config.bookmarkGetter
? createBookmarkGetFigureNode(schema, config.bookmarkGetter)
: createBookmarkWithModal(schema),
});
}

Expand Down Expand Up @@ -170,7 +173,7 @@ export function getOptions(view: EditorView, config: Config): SlashOption[] {
description: 'Add a table',
icon: IconTable,
keywords: ['table', 'spreadsheet'],
node: () => null, // TODO:
node: () => createTable(schema),
});
}

Expand Down Expand Up @@ -255,47 +258,54 @@ function createQuote(schema: Schema) {
// });
// }

// function createBookmark(url: string = '') {
// return new Promise<Node | null>((resolve) => {
// const div = document.createElement('div');
// document.body.appendChild(div);

// const creator = mount(BookmarkCreator, {
// target: div,
// props: {
// url,
// onclose: () => {
// destroy();
// resolve(null);
// },
// oncreate: (url: string) => {
// destroy();
// resolve(
// schema.nodes.figure!.create({}, [
// schema.nodes.bookmark!.create({ url }),
// schema.nodes.figcaption!.create()
// ])
// );
// }
// }
// });
function createBookmarkWithModal(schema: Schema, url: string = '') {
return new Promise<Node | null>((resolve) => {
const div = document.createElement('div');
document.body.appendChild(div);

// function destroy() {
// unmount(creator);
// div.remove();
// }
// });
// }
// Default bookmark getter that just returns the URL
const defaultBookmarkGetter = async (inputUrl: string) => {
return { url: inputUrl };
};

// function createTable() {
// const rows = [];
// for (let i = 0; i < 3; i++) {
// const cells = [];
// for (let j = 0; j < 3; j++) {
// cells.push(schema.nodes.table_cell!.create({}, [schema.nodes.paragraph!.create()]));
// }
// rows.push(schema.nodes.table_row!.create({}, cells));
// }
const creator = mount(BookmarkCreator, {
target: div,
props: {
url,
bookmarkGetter: defaultBookmarkGetter,
onclose: () => {
destroy();
resolve(null);
},
oncreate: (url: string) => {
destroy();
resolve(
schema.nodes.figure!.create({}, [
schema.nodes.bookmark!.create({ url }),
schema.nodes.figcaption!.create()
])
);
}
}
});

// return Promise.resolve(schema.nodes.table!.create({}, [...rows]));
// }
function destroy() {
unmount(creator);
div.remove();
}
});
}

function createTable(schema: Schema) {
const rows = [];
for (let i = 0; i < 3; i++) {
const cells = [];
for (let j = 0; j < 3; j++) {
cells.push(schema.nodes.table_cell!.create({}, [schema.nodes.paragraph!.create()]));
}
rows.push(schema.nodes.table_row!.create({}, cells));
}

return Promise.resolve(schema.nodes.table!.create({}, [...rows]));
}
Loading