Skip to content
Merged
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
6 changes: 2 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
steps:
- uses: actions/checkout@v4

- uses: denoland/setup-deno@v1
- uses: denoland/setup-deno@v2

- name: Run fmt
run: |
Expand All @@ -34,9 +34,7 @@ jobs:
deno task check:types

- name: Install Chromium
run: deno run -A --unstable https://deno.land/x/puppeteer@16.2.0/install.ts
env:
PUPPETEER_PRODUCT: chrome
run: deno run -A npm:puppeteer browsers install chrome

- name: Run tests
run: |
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,12 @@ If you want to use the light or dark theme depending on the user's browser
preference, set the following:

```html
<div data-color-mode="auto" data-light-theme="light" data-dark-theme="dark" class="markdown-body">
<div
data-color-mode="auto"
data-light-theme="light"
data-dark-theme="dark"
class="markdown-body"
>
... markdown body here ...
</div>
```
Expand Down
8 changes: 4 additions & 4 deletions deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "@deno/gfm",
"version": "0.10.0",
"exports": "./mod.ts",
"nodeModulesDir": "auto",
"imports": {
"emoji": "jsr:@denosaurs/emoji@^0.3.1",
"marked": "npm:marked@^12",
Expand All @@ -14,6 +15,7 @@
"sanitize-html": "npm:sanitize-html@^2.13",
"he": "npm:he@^1.2",
"katex": "npm:katex@^0.16",
"css": "npm:css@^3.0.0",
"@std/assert": "jsr:@std/assert@^1.0"
},
"compilerOptions": {
Expand All @@ -27,13 +29,11 @@
"ok": "deno fmt --check && deno lint && deno task check:types && deno task test",
"report": "deno coverage cov_profile --html",
"server": "deno run -A --watch=test/,mod.ts ./test/runTestServer.ts",
"test": "deno test --allow-read --allow-env --allow-write --allow-run --allow-net"
"test": "deno test --allow-sys --allow-read --allow-env --allow-write --allow-run --allow-net"
},
"fmt": {
"exclude": [
"./test/fixtures/alerts.md",
"./test/fixtures/lineBreaks.md",
"./test/fixtures/footnote.md",
"./test/fixtures/",
"./example/content.md"
]
}
Expand Down
2 changes: 1 addition & 1 deletion style.ts

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions style/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
@import "@primer/css/color-modes/themes/dark.scss";
@import "@primer/css/markdown/index.scss";

.dark {
@include primer-colors-dark;
}

.markdown-body {
background-color: var(--color-canvas-default);
color: var(--color-fg-default);
Expand Down
2 changes: 1 addition & 1 deletion style/patch.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import $ from "https://deno.land/x/dax@0.36.0/mod.ts";
import css from "npm:css@3.0.0";
import css from "css";

await $`rm -rf style/node_modules/@primer/primitives`;
await $`npm install`.cwd("./style");
Expand Down
200 changes: 108 additions & 92 deletions test/server_test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { assert, assertEquals } from "@std/assert";
import { browserTest } from "./test_utils.ts";

Deno.test("basic md table with dollar signs", async () => {
Deno.test({
name: "basic md table with dollar signs",
sanitizeResources: false,
sanitizeOps: false,
}, async () => {
await browserTest("basicMarkdownTable", async (page) => {
await page.waitForSelector("table", { timeout: 1000 });
const tableExists = await page.evaluate(() => {
Expand Down Expand Up @@ -78,103 +82,115 @@ Deno.test("basic md table with dollar signs", async () => {
});
});

Deno.test("footnote with style", async () => {
await browserTest("footnotes", async (page) => {
// 1. Test page jump on clicking footnote links
const scrollPositionBefore = await page.evaluate(() => globalThis.scrollY);
await page.click("#footnote-ref-1"); // click the first footnote link. note that we select by id, not href
const scrollPositionAfter = await page.evaluate(() => globalThis.scrollY);
assert(scrollPositionAfter > scrollPositionBefore);
Deno.test(
{ name: "footnote with style", sanitizeResources: false, sanitizeOps: false },
async () => {
await browserTest("footnotes", async (page) => {
// 1. Test page jump on clicking footnote links
const scrollPositionBefore = await page.evaluate(() =>
globalThis.scrollY
);
await page.click("#footnote-ref-1"); // click the first footnote link. note that we select by id, not href
const scrollPositionAfter = await page.evaluate(() => globalThis.scrollY);
assert(scrollPositionAfter > scrollPositionBefore);

await page.click("#footnote-ref-bignote");
const scrollPositionAfter2 = await page.evaluate(() => globalThis.scrollY);
assert(scrollPositionAfter2 === scrollPositionAfter);
await page.click("#footnote-ref-bignote");
const scrollPositionAfter2 = await page.evaluate(() =>
globalThis.scrollY
);
assert(scrollPositionAfter2 === scrollPositionAfter);

await page.click("#footnote-1 > p > a");
const scrollPositionAfter3 = await page.evaluate(() => globalThis.scrollY);
assert(scrollPositionAfter3 < scrollPositionAfter2);
assert(scrollPositionAfter3 > scrollPositionBefore);
await page.click("#footnote-1 > p > a");
const scrollPositionAfter3 = await page.evaluate(() =>
globalThis.scrollY
);
assert(scrollPositionAfter3 < scrollPositionAfter2);
assert(scrollPositionAfter3 > scrollPositionBefore);

// 2. Verify footnote link styling
const beforeContent = await page.evaluate(() => {
const element = document.querySelector("#footnote-ref-1");
if (element) {
return globalThis.getComputedStyle(element, "::before").content;
}
return null;
});
const afterContent = await page.evaluate(() => {
const element = document.querySelector("#footnote-ref-1");
if (element) {
return globalThis.getComputedStyle(element, "::after").content;
}
return null;
});
assertEquals(beforeContent, '"["');
assertEquals(afterContent, '"]"');
// 2. Verify footnote link styling
const beforeContent = await page.evaluate(() => {
const element = document.querySelector("#footnote-ref-1");
if (element) {
return globalThis.getComputedStyle(element, "::before").content;
}
return null;
});
const afterContent = await page.evaluate(() => {
const element = document.querySelector("#footnote-ref-1");
if (element) {
return globalThis.getComputedStyle(element, "::after").content;
}
return null;
});
assertEquals(beforeContent, '"["');
assertEquals(afterContent, '"]"');

// 3. Check Visibility of "Footnotes" H2
const h2Style = await page.evaluate(() => {
const element = document.querySelector("#footnote-label");
if (element) {
const computedStyle = globalThis.getComputedStyle(element);
return {
position: computedStyle.position,
width: computedStyle.width,
height: computedStyle.height,
overflow: computedStyle.overflow,
clip: computedStyle.clip,
wordWrap: computedStyle.wordWrap,
border: computedStyle.border,
};
}
return null;
});
assert(h2Style);
assertEquals(h2Style.position, "absolute");
assertEquals(h2Style.width, "1px");
assertEquals(h2Style.height, "1px");
assertEquals(h2Style.overflow, "hidden");
assertEquals(h2Style.clip, "rect(0px, 0px, 0px, 0px)");
assertEquals(h2Style.wordWrap, "normal");
assertEquals(h2Style.border, "");
// 3. Check Visibility of "Footnotes" H2
const h2Style = await page.evaluate(() => {
const element = document.querySelector("#footnote-label");
if (element) {
const computedStyle = globalThis.getComputedStyle(element);
return {
position: computedStyle.position,
width: computedStyle.width,
height: computedStyle.height,
overflow: computedStyle.overflow,
clip: computedStyle.clip,
wordWrap: computedStyle.wordWrap,
border: computedStyle.border,
};
}
return null;
});
assert(h2Style);
assertEquals(h2Style.position, "absolute");
assertEquals(h2Style.width, "1px");
assertEquals(h2Style.height, "1px");
assertEquals(h2Style.overflow, "hidden");
assertEquals(h2Style.clip, "rect(0px, 0px, 0px, 0px)");
assertEquals(h2Style.wordWrap, "normal");
assertEquals(h2Style.border, "");

// 4. Verify blue box around the footnote after clicking
await page.click("#footnote-ref-1");
const footnoteStyle = await page.evaluate(() => {
const element = document.querySelector("#footnote-1");
if (element) {
return globalThis.getComputedStyle(element)
.outlineColor;
}
return null;
// 4. Verify blue box around the footnote after clicking
await page.click("#footnote-ref-1");
const footnoteStyle = await page.evaluate(() => {
const element = document.querySelector("#footnote-1");
if (element) {
return globalThis.getComputedStyle(element)
.outlineColor;
}
return null;
});
assertEquals(footnoteStyle, "rgb(31, 35, 40)");
});
assertEquals(footnoteStyle, "rgb(31, 35, 40)");
});
});
},
);

Deno.test("yaml style", async () => {
await browserTest("yaml", async (page) => {
const nameStyle = await page.evaluate(() => {
const element = document.querySelector(
"body > main > div > pre > span:nth-child(1)", // doe in the first line
);
if (element) {
return globalThis.getComputedStyle(element).color;
}
return null;
});
assertEquals(nameStyle, "rgb(207, 34, 46)");
Deno.test(
{ name: "yaml style", sanitizeResources: false, sanitizeOps: false },
async () => {
await browserTest("yaml", async (page) => {
const nameStyle = await page.evaluate(() => {
const element = document.querySelector(
"body > main > div > pre > span:nth-child(1)", // doe in the first line
);
if (element) {
return globalThis.getComputedStyle(element).color;
}
return null;
});
assertEquals(nameStyle, "rgb(207, 34, 46)");

const colonStyle = await page.evaluate(() => {
const element = document.querySelector(
"body > main > div > pre > span:nth-child(2)", // : in the first line
);
if (element) {
return globalThis.getComputedStyle(element).color;
}
return null;
const colonStyle = await page.evaluate(() => {
const element = document.querySelector(
"body > main > div > pre > span:nth-child(2)", // : in the first line
);
if (element) {
return globalThis.getComputedStyle(element).color;
}
return null;
});
assertEquals(colonStyle, "rgb(102, 57, 186)");
});
assertEquals(colonStyle, "rgb(102, 57, 186)");
});
});
},
);
5 changes: 1 addition & 4 deletions test/test_utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import {
default as puppeteer,
type Page,
} from "https://deno.land/x/puppeteer@16.2.0/mod.ts";
import { default as puppeteer, type Page } from "npm:puppeteer";
import { CSS, render, type RenderOptions } from "../mod.ts";

type TestCase = {
Expand Down