Radish alpha
r
Radicle web interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Add switch between rendered markdown and raw file
Sebastian Martinez committed 3 years ago
commit 489039c6e3d9c256cfa11123819ae429a7b22426
parent 178d6230cbc0b49c63c93d3327dc9514e6b39c18
7 files changed +161 -149
modified cypress/e2e/projectHeader.spec.ts
@@ -78,9 +78,15 @@ describe("project header", () => {
      "@projectTree56e4e02",
      "@projectReadme",
    ]);
-
    cy.get("div.stat.seed span").should("have.text", "willow.radicle.garden");
-
    cy.get("div.stat.commit-count").should("have.text", "3\n    commit(s)");
-
    cy.get("div.stat.contributor-count").should(
+
    cy.get('[aria-label="Seed"] span').should(
+
      "have.text",
+
      "willow.radicle.garden",
+
    );
+
    cy.get('[aria-label="Commit count"]').should(
+
      "have.text",
+
      "3\n    commit(s)",
+
    );
+
    cy.get('[aria-label="Contributor count"]').should(
      "have.text",
      "1\n    contributor(s)",
    );
@@ -138,35 +144,37 @@ describe("project header", () => {
  });

  it("navigate to commit history", () => {
-
    cy.get("div.stat.commit-count").should("not.have.class", "active").click();
+
    cy.get('[aria-label="Commit count"]')
+
      .should("not.have.class", "active")
+
      .click();
    cy.wait(["@projectCommits"]);
    cy.location().should(location => {
      expect(location.pathname).to.eq(
        "/seeds/willow.radicle.garden/rad:git:hnrk8mbpirp7ua7sy66o4t9soasbq4y8uwgoy/remotes/hyndc7nx9keq76p1bkw9831arcndeeu3trwsc7kxt3osmpi6j9oeke/history/master",
      );
    });
-
    cy.get("div.stat.commit-count").should("have.class", "active");
+
    cy.get('[aria-label="Commit count"]').should("have.class", "active");
  });

  it("navigate to issues listing", () => {
-
    cy.get("div.stat.issue-count").click();
+
    cy.get('[aria-label="Issue count"]').click();
    cy.wait(["@projectIssues"]);
    cy.location().should(location => {
      expect(location.pathname).to.eq(
        "/seeds/willow.radicle.garden/rad:git:hnrk8mbpirp7ua7sy66o4t9soasbq4y8uwgoy/remotes/hyndc7nx9keq76p1bkw9831arcndeeu3trwsc7kxt3osmpi6j9oeke/issues",
      );
    });
-
    cy.get("div.stat.issue-count").should("have.class", "active");
+
    cy.get('[aria-label="Issue count"]').should("have.class", "active");
  });

  it("navigate to patches listing", () => {
-
    cy.get("div.stat.patch-count").click();
+
    cy.get('[aria-label="Patch count"]').click();
    cy.wait(["@projectPatches"]);
    cy.location().should(location => {
      expect(location.pathname).to.eq(
        "/seeds/willow.radicle.garden/rad:git:hnrk8mbpirp7ua7sy66o4t9soasbq4y8uwgoy/remotes/hyndc7nx9keq76p1bkw9831arcndeeu3trwsc7kxt3osmpi6j9oeke/patches",
      );
    });
-
    cy.get("div.stat.patch-count").should("have.class", "active");
+
    cy.get('[aria-label="Patch count"]').should("have.class", "active");
  });
});
modified src/base/projects/Blob.svelte
@@ -1,13 +1,17 @@
<script lang="ts">
  import type { Blob } from "@app/project";
+
  import type { ProjectRoute } from "@app/router/definitions";

-
  import { onMount } from "svelte";
-

-
  import { scrollIntoView } from "@app/utils";
+
  import Readme from "@app/base/projects/Readme.svelte";
+
  import HeaderToggleLabel from "@app/base/projects/HeaderToggleLabel.svelte";
  import ProjectLink from "@app/router/ProjectLink.svelte";
+
  import { isMarkdownPath, scrollIntoView } from "@app/utils";
+
  import { updateProjectRoute } from "@app/router";

  export let blob: Blob;
  export let line: string | null;
+
  export let getImage: (path: string) => Promise<Blob>;
+
  export let activeRoute: ProjectRoute;

  $: lineNumber = line ? parseInt(line.substring(1)) : null;

@@ -24,11 +28,13 @@
  $: if (line) {
    scrollIntoView(line);
  }
-

-
  // Waiting onMount, due to the line numbers still loading.
-
  onMount(() => {
-
    if (line) scrollIntoView(line);
-
  });
+
  const isMarkdown = isMarkdownPath(blob.path);
+
  // If we have a line number we should show the raw output.
+
  let showMarkdown = line ? false : isMarkdown;
+
  const toggleMarkdown = () => {
+
    updateProjectRoute({ hash: undefined });
+
    showMarkdown = !showMarkdown;
+
  };
</script>

<style>
@@ -46,6 +52,12 @@
    border-top-right-radius: var(--border-radius-small);
  }

+
  .file-header .right {
+
    display: flex;
+
    flex-direction: row;
+
    align-items: center;
+
  }
+

  header .file-name {
    font-weight: var(--font-weight-normal);
    white-space: nowrap;
@@ -70,6 +82,10 @@
    margin-right: 0.25rem;
  }

+
  .markdown-toggle {
+
    margin-right: 0.5rem;
+
  }
+

  .line-numbers {
    color: var(--color-foreground-4);
    font-family: var(--font-family-sans-serif);
@@ -126,6 +142,10 @@
    scrollbar-width: none;
  }

+
  .markdown {
+
    max-width: 64rem;
+
  }
+

  .no-scrollbar::-webkit-scrollbar {
    display: none;
  }
@@ -141,51 +161,61 @@
  }
</style>

-
<div>
-
  <div class="file-source">
-
    <header>
-
      <div class="file-header">
-
        <span class="file-name">
-
          <span class="txt-faded">{parentDir}</span>
-
          &#8203;
-
          <span>{blob.info.name}</span>
-
        </span>
+
<div class:markdown={isMarkdown}>
+
  <header>
+
    <div class="file-header">
+
      <span class="file-name">
+
        <span class="txt-faded">{parentDir}</span>
+
        &#8203;
+
        <span>{blob.info.name}</span>
+
      </span>
+
      <div class="right">
+
        {#if isMarkdown}
+
          <div class="markdown-toggle">
+
            <HeaderToggleLabel
+
              active={!showMarkdown}
+
              clickable
+
              on:click={toggleMarkdown}>
+
              Raw
+
            </HeaderToggleLabel>
+
          </div>
+
        {/if}
        <div class="last-commit" title={lastCommit.author.name}>
          <span class="hash">{lastCommit.sha1.slice(0, 7)}</span>
          {lastCommit.summary}
        </div>
      </div>
-
    </header>
-
    <div class="container">
-
      {#if blob.binary}
-
        <div class="binary">
-
          <div>👀</div>
-
          <span class="txt-tiny">Binary content</span>
-
        </div>
+
    </div>
+
  </header>
+
  <div class="container">
+
    {#if blob.binary}
+
      <div class="binary">
+
        <div>👀</div>
+
        <span class="txt-tiny">Binary content</span>
+
      </div>
+
    {:else if showMarkdown}
+
      <Readme content={blob.content} {getImage} {activeRoute} />
+
    {:else}
+
      {#if lineNumber}
+
        <div
+
          class="highlight"
+
          style="top: {lineNumber === 1 ? 1 : 1.5 * lineNumber - 0.5}rem" />
+
      {/if}
+
      <div class="line-numbers">
+
        {#each lineNumbers as lineNumber}
+
          <ProjectLink
+
            projectParams={{ hash: `L${lineNumber}` }}
+
            id="L{lineNumber}">
+
            <span class="line-number" class:highlighted={lineNumber === line} />
+
            {lineNumber}
+
          </ProjectLink>
+
        {/each}
+
      </div>
+
      {#if blob.html}
+
        <pre class="code no-scrollbar">{@html blob.content}</pre>
      {:else}
-
        {#if lineNumber}
-
          <div
-
            class="highlight"
-
            style="top: {lineNumber === 1 ? 1 : 1.5 * lineNumber - 0.5}rem" />
-
        {/if}
-
        <div class="line-numbers">
-
          {#each lineNumbers as lineNumber}
-
            <ProjectLink
-
              projectParams={{ hash: `L${lineNumber}` }}
-
              id="L{lineNumber}">
-
              <span
-
                class="line-number"
-
                class:highlighted={lineNumber === line} />
-
              {lineNumber}
-
            </ProjectLink>
-
          {/each}
-
        </div>
-
        {#if blob.html}
-
          <pre class="code no-scrollbar">{@html blob.content}</pre>
-
        {:else}
-
          <pre class="code no-scrollbar">{blob.content}</pre>
-
        {/if}
+
        <pre class="code no-scrollbar">{blob.content}</pre>
      {/if}
-
    </div>
+
    {/if}
  </div>
</div>
modified src/base/projects/Browser.svelte
@@ -12,7 +12,6 @@

  import Tree from "./Tree.svelte";
  import Blob from "./Blob.svelte";
-
  import Readme from "./Readme.svelte";

  enum Status {
    Loading,
@@ -207,11 +206,7 @@
        {#await getBlob}
          <Loading small center />
        {:then blob}
-
          {#if utils.isMarkdownPath(blob.path)}
-
            <Readme {activeRoute} content={blob.content} {getImage} />
-
          {:else}
-
            <Blob {line} {blob} />
-
          {/if}
+
          <Blob {line} {blob} {getImage} {activeRoute} />
        {:catch}
          <Placeholder icon="🍂">
            <span slot="title">
modified src/base/projects/Header.svelte
@@ -8,7 +8,7 @@
  import CloneButton from "@app/base/projects/CloneButton.svelte";
  import PeerSelector from "@app/base/projects/PeerSelector.svelte";
  import { closeFocused } from "@app/Floating.svelte";
-
  import Stat from "@app/base/projects/Stat.svelte";
+
  import HeaderToggleLabel from "@app/base/projects/HeaderToggleLabel.svelte";

  export let activeRoute: ProjectRoute;
  export let project: Project;
@@ -72,27 +72,6 @@
    flex-wrap: wrap;
    gap: 0.5rem;
  }
-
  .widget {
-
    border-radius: var(--border-radius-small);
-
    min-width: max-content;
-
  }
-
  .not-allowed {
-
    cursor: not-allowed;
-
  }
-
  .not-allowed.widget {
-
    color: var(--color-foreground-5);
-
  }
-
  .stat {
-
    font-family: var(--font-family-monospace);
-
    padding: 0.5rem 0.75rem;
-
    height: 2rem;
-
    line-height: initial;
-
    background: var(--color-foreground-1);
-
  }
-
  .stat.active {
-
    color: var(--color-background);
-
    background: var(--color-foreground);
-
  }

  @media (max-width: 960px) {
    header {
@@ -123,43 +102,47 @@
  {/if}
  <span>
    {#if seed.api.host}
-
      <Stat
+
      <HeaderToggleLabel
        clickable
+
        ariaLabel="Seed"
        title="Project data is fetched from this seed"
        on:click={goToSeed}>
        <span>{seed.api.host}</span>
-
      </Stat>
+
      </HeaderToggleLabel>
    {/if}
  </span>
-
  <Stat
+
  <HeaderToggleLabel
+
    ariaLabel="Commit count"
    clickable
    active={activeRoute.params.view.resource === "history"}
    on:click={() => toggleContent("history", true)}>
    <span class="txt-bold">{tree.stats.commits}</span>
    commit(s)
-
  </Stat>
+
  </HeaderToggleLabel>
  {#if project.issues}
-
    <Stat
+
    <HeaderToggleLabel
+
      ariaLabel="Issue count"
      active={activeRoute.params.view.resource === "issues"}
-
      notAllowed={project.issues === 0}
+
      disabled={project.issues === 0}
      clickable={project.issues > 0}
      on:click={() => toggleContent("issues", false)}>
      <span class="txt-bold">{project.issues}</span>
      issue(s)
-
    </Stat>
+
    </HeaderToggleLabel>
  {/if}
  {#if project.patches}
-
    <Stat
+
    <HeaderToggleLabel
+
      ariaLabel="Patch count"
      clickable={project.patches > 0}
      active={activeRoute.params.view.resource === "patches"}
      disabled={project.patches === 0}
      on:click={() => toggleContent("patches", false)}>
      <span class="txt-bold">{project.patches}</span>
      patch(es)
-
    </Stat>
+
    </HeaderToggleLabel>
  {/if}
-
  <Stat>
+
  <HeaderToggleLabel ariaLabel="Contributor count">
    <span class="txt-bold">{tree.stats.contributors}</span>
    contributor(s)
-
  </Stat>
+
  </HeaderToggleLabel>
</header>
added src/base/projects/HeaderToggleLabel.svelte
@@ -0,0 +1,49 @@
+
<script lang="ts">
+
  export let title: string | undefined = undefined;
+
  export let ariaLabel: string | undefined = undefined;
+
  export let active = false;
+
  export let clickable = false;
+
  export let disabled = false;
+
</script>
+

+
<style>
+
  .stat {
+
    font-family: var(--font-family-monospace);
+
    font-size: var(--font-size-tiny);
+
    padding: 0.5rem 0.75rem;
+
    padding-bottom: 1rem; /* moving the content a tad higher to match the previous span usage */
+
    height: 2rem;
+
    background: var(--color-foreground-1);
+
    border: none;
+
    color: var(--color-foreground);
+
    border-radius: var(--border-radius-small);
+
    min-width: max-content;
+
  }
+
  .active {
+
    color: var(--color-background);
+
    background: var(--color-foreground) !important;
+
    background-color: var(--color-foreground);
+
  }
+
  .clickable {
+
    cursor: pointer;
+
  }
+
  .clickable:hover {
+
    background-color: var(--color-foreground-2);
+
  }
+
  .not-allowed {
+
    cursor: not-allowed;
+
    color: var(--color-foreground-5);
+
  }
+
</style>
+

+
<button
+
  {title}
+
  {disabled}
+
  class:active
+
  class:clickable
+
  class:not-allowed={disabled}
+
  class="stat"
+
  aria-label={ariaLabel}
+
  on:click>
+
  <slot />
+
</button>
modified src/base/projects/Readme.svelte
@@ -14,9 +14,8 @@
<style>
  article {
    padding: 2rem;
-
    max-width: 64rem;
+
    width: 100%;
    background: var(--color-foreground-1);
-
    border-radius: var(--border-radius);
  }
</style>

deleted src/base/projects/Stat.svelte
@@ -1,52 +0,0 @@
-
<script lang="ts">
-
  import { createEventDispatcher } from "svelte";
-

-
  export let title: string | undefined = undefined;
-
  export let active = false;
-
  export let clickable = false;
-
  export let notAllowed = false;
-

-
  const dispatch = createEventDispatcher();
-
</script>
-

-
<style>
-
  .stat {
-
    font-family: var(--font-family-monospace);
-
    font-size: var(--font-size-tiny);
-
    padding: 0.5rem 0.75rem;
-
    padding-bottom: 1rem; /* moving the inner text a tad higher to match the previous span usage */
-
    height: 2rem;
-
    background: var(--color-foreground-1);
-
    border: none;
-
    color: var(--color-foreground);
-
    border-radius: var(--border-radius-small);
-
    min-width: max-content;
-
  }
-
  .active {
-
    color: var(--color-background);
-
    background: var(--color-foreground) !important;
-
    background-color: var(--color-foreground);
-
  }
-
  .clickable {
-
    cursor: pointer;
-
  }
-
  .clickable:hover {
-
    background-color: var(--color-foreground-2);
-
  }
-
  .not-allowed {
-
    cursor: not-allowed;
-
    color: var(--color-foreground-5);
-
  }
-
</style>
-

-
<button
-
  {title}
-
  class:active
-
  class:not-allowed={notAllowed}
-
  class:clickable
-
  class="stat clickable"
-
  on:click={() => {
-
    if (!notAllowed) dispatch("click");
-
  }}>
-
  <slot />
-
</button>