Radish alpha
r
Radicle web interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Run source highlighting in router to prevent showing intermediate state
Thomas Scholtes committed 2 years ago
commit 8ef8ce5b81fab80ecc701338921d07377a071037
parent dbad9ddeefb911dc9e88bf113152d8c442ada8d4
4 files changed +43 -45
modified src/lib/syntax.ts
@@ -11,7 +11,7 @@ import sourceToml from "@wooorm/starry-night/lang/source.toml";
import sourceTsx from "@wooorm/starry-night/lang/source.tsx";
import { createStarryNight, common } from "@wooorm/starry-night";

-
export type MaybeHighlighted = Root | undefined;
+
export { type Root };

export const grammars = [
  ...common,
@@ -36,7 +36,7 @@ let starryNight: Awaited<ReturnType<typeof createStarryNight>>;
export async function highlight(
  content: string,
  grammar: string,
-
): Promise<MaybeHighlighted> {
+
): Promise<Root> {
  if (starryNight === undefined) {
    starryNight = await createStarryNight(grammars, {
      getOnigurumaUrlFetch: () => new URL(onigurumaWASMUrl, import.meta.url),
modified src/views/projects/Blob.svelte
@@ -1,11 +1,10 @@
<script lang="ts">
  import type { Blob } from "@httpd-client";
-
  import type { MaybeHighlighted } from "@app/lib/syntax";

  import { afterUpdate, onDestroy, onMount } from "svelte";
  import { toHtml } from "hast-util-to-html";

-
  import { highlight } from "@app/lib/syntax";
+
  import * as Syntax from "@app/lib/syntax";
  import { isMarkdownPath, twemoji } from "@app/lib/utils";
  import { lineNumbersGutter } from "@app/lib/syntax";

@@ -15,66 +14,58 @@
  export let path: string;
  export let hash: string | undefined = undefined;
  export let blob: Blob;
+
  export let highlighted: Syntax.Root | undefined;
  export let rawPath: string;

-
  $: fileExtension = blob.path.split(".").pop() ?? "";
  $: lastCommit = blob.lastCommit;

  $: parentDir = blob.path
    .match(/^.*\/|/)
    ?.values()
    .next().value;
-
  let content: MaybeHighlighted = undefined;

-
  onMount(async () => {
-
    window.addEventListener("hashchange", setTarget);
-
  });
+
  $: content = highlighted ? lineNumbersGutter(highlighted) : undefined;
+

+
  let selectedLineId: string | undefined = undefined;
+
  updateSelectedLineId();

-
  $: {
-
    if (blob.content) {
-
      highlight(blob.content, fileExtension)
-
        .then(output => {
-
          if (output) {
-
            content = lineNumbersGutter(output);
-
          }
-
        })
-
        /* eslint-disable-next-line @typescript-eslint/no-empty-function */
-
        .catch(() => {
-
          // TODO: handle error.
-
        });
+
  function updateSelectedLineId() {
+
    const fragmentId = window.location.hash.substr(1);
+
    if (fragmentId && fragmentId.match(/^L\d+$/)) {
+
      selectedLineId = fragmentId;
+
    } else {
+
      selectedLineId = undefined;
    }
  }

-
  onDestroy(() => {
-
    window.removeEventListener("hashchange", setTarget);
-
  });
-

-
  afterUpdate(() => {
-
    setTarget();
-
  });
-

  $: isMarkdown = isMarkdownPath(blob.path);
-
  $: showMarkdown = isMarkdown;
+
  $: showMarkdown = isMarkdown && selectedLineId === undefined;

  function toggleMarkdown() {
    window.location.hash = "";
    showMarkdown = !showMarkdown;
  }

-
  function setTarget() {
+
  afterUpdate(() => {
    for (const item of document.getElementsByClassName("highlight")) {
      item.classList.remove("highlight");
    }
-
    const fragmentId = window.location.hash.substr(1);
-
    if (fragmentId && fragmentId.match(/L\d+/)) {
-
      showMarkdown = false;
-
      const target = document.getElementById(fragmentId);
+
    if (selectedLineId) {
+
      const target = document.getElementById(selectedLineId);
      if (target) {
        target.classList.add("highlight");
        target.scrollIntoView();
      }
    }
-
  }
+
  });
+

+
  onMount(async () => {
+
    window.addEventListener("hashchange", updateSelectedLineId);
+
  });
+

+
  onDestroy(() => {
+
    window.removeEventListener("hashchange", updateSelectedLineId);
+
  });
</script>

<style>
modified src/views/projects/Browser.svelte
@@ -155,6 +155,7 @@
            {path}
            {hash}
            blob={blobResult.blob}
+
            highlighted={blobResult.highlighted}
            rawPath={utils.getRawBasePath(project.id, baseUrl, commit)} />
        {:else}
          <Placeholder emoji="🍂">
modified src/views/projects/router.ts
@@ -15,6 +15,7 @@ import { get } from "svelte/store";

import { HttpdClient } from "@httpd-client";
import { activeRouteStore, push, replace, routeToPath } from "@app/lib/router";
+
import * as Syntax from "@app/lib/syntax";

export const COMMITS_PER_PAGE = 30;

@@ -78,7 +79,7 @@ interface LoadedSourceBrowsingParams {
}

export type BlobResult =
-
  | { ok: true; blob: Blob }
+
  | { ok: true; blob: Blob; highlighted: Syntax.Root | undefined }
  | { ok: false; error: { message: string; path: string } };

export type ProjectLoadedView =
@@ -216,17 +217,22 @@ export async function loadProjectRoute(

        const path = params.path || "/";
        try {
+
          let blob: Blob;
          if (path === "/") {
-
            blobResult = {
-
              ok: true,
-
              blob: await api.project.getReadme(project.id, commit),
-
            };
+
            blob = await api.project.getReadme(project.id, commit);
          } else {
-
            blobResult = {
-
              ok: true,
-
              blob: await api.project.getBlob(project.id, commit, path),
-
            };
+
            blob = await api.project.getBlob(project.id, commit, path);
          }
+
          blobResult = {
+
            ok: true,
+
            blob,
+
            highlighted: blob.content
+
              ? await Syntax.highlight(
+
                  blob.content,
+
                  blob.path.split(".").pop() ?? "",
+
                )
+
              : undefined,
+
          };
        } catch {
          if (path === "/") {
            blobResult = {