Skip to content
This repository has been archived by the owner on Apr 1, 2020. It is now read-only.

Markdown Syntax Highlights #2332

Merged
merged 13 commits into from
Jul 26, 2018
6 changes: 1 addition & 5 deletions browser/src/Services/Browser/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Entry point for browser integration plugin
*/

import { ipcRenderer, shell, WebviewTag } from "electron"
import { shell, WebviewTag } from "electron"
import * as React from "react"

import * as Oni from "oni-api"
Expand Down Expand Up @@ -290,10 +290,6 @@ export const activate = (
detail: "",
enabled: isBrowserScrollCommandEnabled,
})

ipcRenderer.on("open-oni-browser", (event: string, args: string) => {
openUrl(args)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left over from previous PR, tidied up in this one.

})
}

export const registerAchievements = (achievements: AchievementsManager) => {
Expand Down
1 change: 1 addition & 0 deletions browser/src/Services/Configuration/DefaultConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ const BaseConfiguration: IConfigurationValues = {

"experimental.markdownPreview.enabled": false,
"experimental.markdownPreview.autoScroll": true,
"experimental.markdownPreview.syntaxTheme": "atom-one-dark",

"experimental.neovim.transport": "stdio",
// TODO: Enable pipe transport for Windows
Expand Down
1 change: 1 addition & 0 deletions browser/src/Services/Configuration/IConfigurationValues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export interface IConfigurationValues {
// Whether the markdown preview pane should be shown
"experimental.markdownPreview.enabled": boolean
"experimental.markdownPreview.autoScroll": boolean
"experimental.markdownPreview.syntaxTheme": string

// The transport to use for Neovim
// Valid values are "stdio" and "pipe"
Expand Down
2 changes: 2 additions & 0 deletions extensions/oni-plugin-markdown-preview/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"tbd-dependencies": {
"marked": "^0.4.0",
"dompurify": "1.0.2",
"highlight.js": "^9.12.0",
"oni-types": "^0.0.4",
"oni-api": "^0.0.9"
},
Expand All @@ -31,6 +32,7 @@
"rimraf": "^2.6.2"
},
"tbd-devDependencies": {
"@types/highlight.js": "^9.12.2",
"typescript": "2.5.3",
"rimraf": "2.6.2"
}
Expand Down
26 changes: 26 additions & 0 deletions extensions/oni-plugin-markdown-preview/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { EventCallback, IDisposable, IEvent } from "oni-types"

import * as dompurify from "dompurify"
import * as hljs from "highlight.js"
import * as marked from "marked"
import * as Oni from "oni-api"
import * as React from "react"
Expand Down Expand Up @@ -84,6 +85,9 @@ class MarkdownPreview extends React.PureComponent<IMarkdownPreviewProps, IMarkdo

private generateContainerStyle(): string {
const colors = this.state.colors
const syntaxHighlightTheme = this.props.oni.configuration.getValue(
"experimental.markdownPreview.syntaxTheme",
)

const codeBlockStyle = `
background: ${colors.codeBackground};
Expand All @@ -95,6 +99,8 @@ class MarkdownPreview extends React.PureComponent<IMarkdownPreviewProps, IMarkdo
`

return `
<link rel="stylesheet" href="node_modules/highlight.js/styles/${syntaxHighlightTheme}.css">

<style>
.oniPluginMarkdownPreviewContainerStyle {
padding: 1em 1em 1em 1em;
Expand Down Expand Up @@ -143,6 +149,26 @@ class MarkdownPreview extends React.PureComponent<IMarkdownPreviewProps, IMarkdo
markdownLines.splice(0, 0, generateAnchor(i))
markdownLines.push(generateAnchor(originalLinesCount - 1))

marked.setOptions({
baseUrl: this.props.oni.workspace.activeWorkspace,
highlight(code, lang) {
const languageExists = hljs.getLanguage(lang)
const languageNotDefinedOrInvalid =
typeof lang === "undefined" ||
(typeof languageExists === "undefined" && lang !== "nohighlight")

if (languageNotDefinedOrInvalid) {
return hljs.highlightAuto(code).value
}

if (lang === "nohighlight") {
return code
}

return hljs.highlight(lang, code).value
},
})

return marked(markdownLines.join("\n"))
}

Expand Down
2 changes: 1 addition & 1 deletion main/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ export function createWindow(

currentWindow.webContents.on("will-navigate", (event, url) => {
event.preventDefault()
currentWindow.webContents.send("open-oni-browser", url)
currentWindow.webContents.send("execute-command", "browser.openUrl", url)
})

windows.push(currentWindow)
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,7 @@
"electron-settings": "^3.1.4",
"find-up": "2.1.0",
"fs-extra": "^5.0.0",
"highlight.js": "^9.12.0",
"json5": "^1.0.1",
"keyboard-layout": "^2.0.13",
"marked": "^0.4.0",
Expand Down Expand Up @@ -888,12 +889,13 @@
"@types/electron-settings": "^3.1.1",
"@types/enzyme": "^3.1.8",
"@types/fs-extra": "^5.0.2",
"@types/highlight.js": "^9.12.2",
"@types/jest": "^22.1.3",
"@types/jsdom": "11.0.0",
"@types/json5": "^0.0.29",
"@types/lodash": "4.14.38",
"@types/lolex": "2.1.0",
"@types/marked": "^0.3.0",
"@types/marked": "^0.4.0",
"@types/minimatch": "3.0.1",
"@types/minimist": "1.1.29",
"@types/mkdirp": "0.3.29",
Expand Down
83 changes: 78 additions & 5 deletions test/ci/MarkdownPreviewTest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,21 @@
*/

import { Assertor } from "./Assert"
import { awaitEditorMode, getTemporaryFilePath, insertText, navigateToFile } from "./Common"
import {
awaitEditorMode,
getElementByClassName,
getTemporaryFilePath,
insertText,
navigateToFile,
} from "./Common"

import * as Oni from "oni-api"

interface IMarkdownPreviewPlugin {
isPaneOpen(): boolean
getUnrenderedContent(): string
getRenderedContent(): string
toggle(): void
}

export const settings = {
Expand All @@ -24,25 +31,91 @@ export async function test(oni: Oni.Plugin.Api) {

await oni.automation.waitForEditors()

// Wait for Plugin to be loaded
await oni.automation.waitFor(() => oni.plugins.loaded)
const markdownPlugin = oni.plugins.getPlugin(
"oni-plugin-markdown-preview",
) as IMarkdownPreviewPlugin
assert.defined(markdownPlugin, "plugin instance")

assert.assert(!markdownPlugin.isPaneOpen(), "Preview pane is not initially closed")
// Check its not open by default
assert.assert(!markdownPlugin.isPaneOpen(), "Preview pane is initially closed.")

await navigateToFile(getTemporaryFilePath("md"), oni)
// Check it opens when navigating into a markdown file.
const markdownFilePath = getTemporaryFilePath("md")
await navigateToFile(markdownFilePath, oni)
await oni.automation.waitFor(() => markdownPlugin.isPaneOpen())

assert.isEmpty(
markdownPlugin.getUnrenderedContent().trim(),
"Preview pane for empty Markdown buffer",
"Preview pane shown for Markdown buffer.",
)

// Check a Title is rendered correctly.
await insertText(oni, "# Title 1")
assert.contains(
markdownPlugin.getRenderedContent(),
">Title 1</h1>",
"Preview pane with rendered header element",
"Preview pane with renders header element.",
)

// Check syntax highlights are applied.
oni.automation.sendKeys("o")
await oni.automation.waitFor(() => oni.editors.activeEditor.mode === "insert")

oni.automation.sendKeys("```<enter>")
oni.automation.sendKeys("const test = 'Oni'<enter>")
oni.automation.sendKeys("```")
oni.automation.sendKeys("<esc>")

await oni.automation.waitFor(() => oni.editors.activeEditor.mode === "normal")

assert.contains(
markdownPlugin.getRenderedContent(),
"code>",
"Code block present in preview HTML.",
)

assert.assert(
getElementByClassName("hljs-keyword").innerText === "const",
"Syntax highlights present in preview HTML.",
)

// Finally, test swapping between files.
// Swapping to a non-MD file should close it.
// Swapping to an MD file should open it.
// Closing the MD preview manually should cause it to remain closed.

const nonMDFilePath = getTemporaryFilePath("ts")

await navigateToFile(nonMDFilePath, oni)
await oni.automation.waitFor(
() => oni.editors.activeEditor.activeBuffer.language === "typescript",
)
assert.assert(!markdownPlugin.isPaneOpen(), "Preview pane is closed for non-MD file.")

await navigateToFile(markdownFilePath, oni)
await oni.automation.waitFor(
() => oni.editors.activeEditor.activeBuffer.language === "markdown",
)
assert.assert(markdownPlugin.isPaneOpen(), "Preview pane opens for MD file.")

// Manually closing preview, should remain closed now.
markdownPlugin.toggle()
assert.assert(!markdownPlugin.isPaneOpen(), "Preview pane closes on toggle.")

await navigateToFile(nonMDFilePath, oni)
await oni.automation.waitFor(
() => oni.editors.activeEditor.activeBuffer.language === "typescript",
)
await navigateToFile(markdownFilePath, oni)
await oni.automation.waitFor(
() => oni.editors.activeEditor.activeBuffer.language === "markdown",
)

// Should remain closed when swapping back in.
assert.assert(
!markdownPlugin.isPaneOpen(),
"Preview pane remains closed for MD file when manually closed.",
)
}
14 changes: 11 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@
"@types/minimatch" "*"
"@types/node" "*"

"@types/highlight.js@^9.12.2":
version "9.12.3"
resolved "https://registry.yarnpkg.com/@types/highlight.js/-/highlight.js-9.12.3.tgz#b672cfaac25cbbc634a0fd92c515f66faa18dbca"

"@types/jest@^22.1.3":
version "22.1.3"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-22.1.3.tgz#25da391935e6fac537551456f077ce03144ec168"
Expand All @@ -134,9 +138,9 @@
version "2.1.0"
resolved "https://registry.yarnpkg.com/@types/lolex/-/lolex-2.1.0.tgz#7a53611a6c970574173a7d92ce9a0da000652725"

"@types/marked@^0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@types/marked/-/marked-0.3.0.tgz#583c223dd33385a1dda01aaf77b0cd0411c4b524"
"@types/marked@^0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@types/marked/-/marked-0.4.0.tgz#057a6165703e7419217f8ffc6887747f980b6315"

"@types/minimatch@*":
version "3.0.3"
Expand Down Expand Up @@ -4795,6 +4799,10 @@ he@1.1.1, he@1.1.x:
version "1.1.1"
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"

highlight.js@^9.12.0:
version "9.12.0"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e"

hmac-drbg@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
Expand Down