Merge pull request #973 from savetheclocktower/regenerate-github-css

[markdown-preview] Add dark mode for GitHub-style preview
This commit is contained in:
Andrew Dupont 2024-04-20 11:35:14 -07:00 committed by GitHub
commit b1b6883c57
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 5251 additions and 528 deletions

View File

@ -8,44 +8,43 @@ It is currently enabled for `.markdown`, `.md`, `.mdown`, `.mkd`, `.mkdown`, `.r
## Customize
By default Markdown Preview uses the colors of the active syntax theme. Enable `Use GitHub.com style` in the __package settings__ to make it look closer to how markdown files get rendered on github.com.
By default Markdown Preview uses the colors of the active syntax theme. Enable **Use GitHub.com Style** in the __package settings__ to make it look closer to how markdown files get rendered on github.com.
![markdown-preview GitHub style](https://cloud.githubusercontent.com/assets/378023/10013087/24ccc7ec-6149-11e5-97ea-53a842a715ea.png)
To customize even further, the styling can be overridden in your `styles.less` file. For example:
When **Use GitHub.com Style** is selected, you can further customize the theme of the Markdown preview with the **GitHub.com Style Mode** setting. Since the GitHub website has a light theme and a dark theme, `markdown-preview` allows you to choose which theme to use when previewing your files. By default, it will use whatever mode is preferred by your system, but you can opt into “Light” or “Dark” to force it to use a particular theme.
No matter which theme you use, you can apply further customizations in your `styles.less` file. For example:
```css
.markdown-preview.markdown-preview {
.markdown-preview pre {
background-color: #444;
}
```
## Syntax Highlighting Language Identifier
## Language identifiers in fenced code blocks
While a verbose specification of Markdown, mostly, ensures the content of Markdown will look the same everywhere it's shipped, the same isn't true of code block language identifiers.
A detailed Markdown specification helps to ensure that Markdown is displayed consistently across multiple parsers. Sadly, the same isnt true of code block language identifiers — the strings you use to tell the renderer what sort of code is inside a code block.
A "code block language identifier" is the string you use to tell the Markdown renderer what code is inside a code block of your Markdown document.
The CommonMark specification [explicitly avoids standardizing these identifiers](https://spec.commonmark.org/0.31.2/#info-string):
Nearly every Markdown rendering system supports different strings to specify your language than each other. `Markdown-Preview` has implemented several valid Language Identifier systems to help ensure that your Markdown will look the same no matter where you publish it!
> The first word of the info string is typically used to specify the language of the code sample, and rendered in the class attribute of the code tag. However, this spec does not mandate any particular treatment of the info string.
In the settings, you can select from a list of different popular Language Identification systems that can then be used in your code blocks. This means that they will still be valid when shipping them to whatever platform of your choice.
There are several valid ways to infer specific languages from language identifiers such as `js`, `less`, `coffee`, and `c`. This package supports the following systems, configured via the **Syntax Highlighting Language Identifiers** setting:
Currently, `Markdown-Preview` supports the following:
* [Linguist](https://github.com/github-linguist/linguist): Used by GitHub (previously the default and only language identification system).
* [Chroma](https://github.com/alecthomas/chroma): Used by CodeBerg/Gitea/Hugo/Goldmark.
* [Rouge](https://github.com/rouge-ruby/rouge): Used by GitLab/Jekyll.
* [HighlightJS](https://highlightjs.org/): Used in a number of places, but most relevantly on the [Pulsar Package Registry](https://web.pulsar-edit.dev/) website.
* Linguist: Used by GitHub (Previously the default and only language identification system)
* Chroma: Used by CodeBerg/Gitea/Hugo/Goldmark
* Rouge: Used by GitLab/Jekyll
* HighlightJS: Used by Markdown-IT/Pulsar Package Website
If none of these systems meets your needs, you may specify custom language identifiers. This may not be as portable as the systems described above, but it will at least produce the desired outcome on your own system.
The setting **Custom Syntax Highlighting Language Identifiers** lets you define a list of custom language identifiers that match up to languages available within your Pulsar installation.
Of course, not all Markdown content is destined to be shared, `Markdown-Preview` even lets you specify custom Language Identifiers to be used within your Markdown code blocks.
The setting `Custom Syntax Highlighting Language Identifiers` lets you define a list of custom language identifiers that match up to languages available within your Pulsar installation
For example, if you wanted to highlight your code like JavaScript by just using `j` as your Code Block language Identifier and `p` to use Python Syntax Highlighting, you could add the following to this setting:
For example, if you wanted to map `j` to JavaScript and `p` to Python, youd add the following text to the **Custom Syntax Highlighting Language Identifiers** field:
```
j: source.js, p: source.python
```
And that's it, now anytime you use that language identifier it will be highlighted exactly the way you want. Of course your preference of language identification system will still be used, in addition to your custom list.
Now `markdown-preview` will understand what to do with fenced code blocks that begin with <code>\`\`\`j</code> or <code>\`\`\`p</code>. These custom identifiers will work alongside whatever system youve chosen with **Syntax Highlighting Language Identifiers**, but will supersede that system in the event of conflict.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,448 +0,0 @@
// All of our block level items should have the same margin
@margin: 16px;
// This is styling for generic markdownized text. Anything you put in a
// container with .markdown-body on it should render generally well. It also
// includes some GitHub Flavored Markdown specific styling (like @mentions)
.markdown-body {
overflow: hidden;
font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;
font-size: 16px;
line-height: 1.6;
word-wrap: break-word;
> *:first-child {
margin-top: 0 !important;
}
> *:last-child {
margin-bottom: 0 !important;
}
// Anchors like <a name="examples">. These sometimes end up wrapped around
// text when users mistakenly forget to close the tag or use self-closing tag
// syntax. We don't want them to appear like links.
// FIXME: a:not(:link):not(:visited) would be a little clearer here (and
// possibly faster to match), but it breaks styling of <a href> elements due
// to https://bugs.webkit.org/show_bug.cgi?id=142737.
a:not([href]) {
color: inherit;
text-decoration: none;
}
// Link Colors
.absent {
color: #c00;
}
.anchor {
position: absolute;
top: 0;
left: 0;
display: block;
padding-right: 6px;
padding-left: 30px;
margin-left: -30px;
&:focus {
outline: none;
}
}
// Headings
h1, h2, h3, h4, h5, h6 {
position: relative;
margin-top: 1em;
margin-bottom: @margin;
font-weight: bold;
line-height: 1.4;
.octicon-link {
display: none;
color: #000;
vertical-align: middle;
}
&:hover .anchor {
padding-left: 8px;
margin-left: -30px;
text-decoration: none;
.octicon-link {
display: inline-block;
}
}
tt,
code {
font-size: inherit;
}
}
h1 {
padding-bottom: 0.3em;
font-size: 2.25em;
line-height: 1.2;
border-bottom: 1px solid #eee;
.anchor {
line-height: 1;
}
}
h2 {
padding-bottom: 0.3em;
font-size: 1.75em;
line-height: 1.225;
border-bottom: 1px solid #eee;
.anchor {
line-height: 1;
}
}
h3 {
font-size: 1.5em;
line-height: 1.43;
.anchor {
line-height: 1.2;
}
}
h4 {
font-size: 1.25em;
.anchor {
line-height: 1.2;
}
}
h5 {
font-size: 1em;
.anchor {
line-height: 1.1;
}
}
h6 {
font-size: 1em;
color: #777;
.anchor {
line-height: 1.1;
}
}
p,
blockquote,
ul, ol, dl,
table,
pre {
margin-top: 0;
margin-bottom: @margin;
}
hr {
height: 4px;
padding: 0;
margin: @margin 0;
background-color: #e7e7e7;
border: 0 none;
}
// Lists, Blockquotes & Such
ul,
ol {
padding-left: 2em;
&.no-list {
padding: 0;
list-style-type: none;
}
}
// Did someone complain about list spacing? Encourage them
// to create the spacing with their markdown formatting.
// List behavior should be controled by the markup, not the css.
//
// For lists with padding between items, use blank
// lines between items. This will generate paragraphs with
// padding to space things out.
//
// - item
//
// - item
//
// - item
//
// For list without padding, don't use blank lines.
//
// - item
// - item
// - item
//
// Modifying the css to emulate these behaviors merely brakes
// one case in the process of solving another. Don't change
// this unless it's really really a bug.
ul ul,
ul ol,
ol ol,
ol ul {
margin-top: 0;
margin-bottom: 0;
}
li > p {
margin-top: @margin;
}
dl {
padding: 0;
}
dl dt {
padding: 0;
margin-top: @margin;
font-size: 1em;
font-style: italic;
font-weight: bold;
}
dl dd {
padding: 0 @margin;
margin-bottom: @margin;
}
blockquote {
padding: 0 15px;
color: #777;
border-left: 4px solid #ddd;
> :first-child {
margin-top: 0;
}
> :last-child {
margin-bottom: 0;
}
}
// Tables
table {
display: block;
width: 100%;
overflow: auto;
word-break: normal;
word-break: keep-all; // For Firefox to horizontally scroll wider tables.
th {
font-weight: bold;
}
th, td {
padding: 6px 13px;
border: 1px solid #ddd;
}
tr {
background-color: #fff;
border-top: 1px solid #ccc;
&:nth-child(2n) {
background-color: #f8f8f8;
}
}
}
// Images & Stuff
img {
max-width: 100%;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.emoji {
max-width: none;
}
// Gollum Image Tags
// Framed
span.frame {
display: block;
overflow: hidden;
& > span {
display: block;
float: left;
width: auto;
padding: 7px;
margin: 13px 0 0;
overflow: hidden;
border: 1px solid #ddd;
}
span img {
display: block;
float: left;
}
span span {
display: block;
padding: 5px 0 0;
clear: both;
color: #333;
}
}
span.align-center {
display: block;
overflow: hidden;
clear: both;
& > span {
display: block;
margin: 13px auto 0;
overflow: hidden;
text-align: center;
}
span img {
margin: 0 auto;
text-align: center;
}
}
span.align-right {
display: block;
overflow: hidden;
clear: both;
& > span {
display: block;
margin: 13px 0 0;
overflow: hidden;
text-align: right;
}
span img {
margin: 0;
text-align: right;
}
}
span.float-left {
display: block;
float: left;
margin-right: 13px;
overflow: hidden;
span {
margin: 13px 0 0;
}
}
span.float-right {
display: block;
float: right;
margin-left: 13px;
overflow: hidden;
& > span {
display: block;
margin: 13px auto 0;
overflow: hidden;
text-align: right;
}
}
// Inline code snippets
code,
tt {
padding: 0;
padding-top: 0.2em;
padding-bottom: 0.2em;
margin: 0;
font-size: 85%;
background-color: rgba(0,0,0,0.04);
border-radius: 3px; // don't add padding, gives scrollbars
&:before,
&:after {
letter-spacing: -0.2em; // this creates padding
content: "\00a0";
}
br { display: none; }
}
del code { text-decoration: inherit; }
// Code tags within code blocks (<pre>s)
pre > code {
padding: 0;
margin: 0;
font-size: 100%;
word-break: normal;
white-space: pre;
background: transparent;
border: 0;
}
.highlight {
margin-bottom: @margin;
}
.highlight pre,
pre {
padding: @margin;
overflow: auto;
font-size: 85%;
line-height: 1.45;
background-color: #f7f7f7;
border-radius: 3px;
}
.highlight pre {
margin-bottom: 0;
word-break: normal;
}
pre {
word-wrap: normal;
}
pre code,
pre tt {
display: inline;
max-width: initial;
padding: 0;
margin: 0;
overflow: initial;
line-height: inherit;
word-wrap: normal;
background-color: transparent;
border: 0;
&:before,
&:after {
content: normal;
}
}
kbd {
display: inline-block;
padding: 3px 5px;
font-size: 11px;
line-height: 10px;
color: #555;
vertical-align: middle;
background-color: #fcfcfc;
border: solid 1px #ccc;
border-bottom-color: #bbb;
border-radius: 3px;
box-shadow: inset 0 -1px 0 #bbb;
}
}

View File

@ -13,12 +13,12 @@ function getUserLanguageIds() {
let pairs = usersLanguageIDs.split(",");
for (let i = 0; i < pairs.length; i++) {
let split = pairs[i].split(":");
obj[split[0].trim()] = split[1].trim();
let split = pairs[i].split(":");
obj[split[0].trim()] = split[1].trim();
}
return obj;
} catch(err) {
atom.notifications.addError(`Unable to load Markdown Preview Custom Syntax Highlighting Language Identifiers\n${err.toString()}`);
return {};
@ -61,7 +61,7 @@ function getLanguageIds() {
}
module.exports = {
scopeForFenceName (fenceName) {
scopeForFenceName(fenceName) {
fenceName = fenceName.toLowerCase()
let scopesByFenceName = getLanguageIds();

View File

@ -7,11 +7,11 @@ const fs = require('fs-plus')
const renderer = require('./renderer')
module.exports = class MarkdownPreviewView {
static deserialize (params) {
static deserialize(params) {
return new MarkdownPreviewView(params)
}
constructor ({ editorId, filePath }) {
constructor({ editorId, filePath }) {
this.editorId = editorId
this.filePath = filePath
this.element = document.createElement('div')
@ -34,7 +34,7 @@ module.exports = class MarkdownPreviewView {
}
}
serialize () {
serialize() {
return {
deserializer: 'MarkdownPreviewView',
filePath: this.getPath() != null ? this.getPath() : this.filePath,
@ -42,19 +42,19 @@ module.exports = class MarkdownPreviewView {
}
}
copy () {
copy() {
return new MarkdownPreviewView({
editorId: this.editorId,
filePath: this.getPath() != null ? this.getPath() : this.filePath
})
}
destroy () {
destroy() {
this.disposables.dispose()
this.element.remove()
}
registerScrollCommands () {
registerScrollCommands() {
this.disposables.add(
atom.commands.add(this.element, {
'core:move-up': () => {
@ -79,20 +79,20 @@ module.exports = class MarkdownPreviewView {
)
}
onDidChangeTitle (callback) {
onDidChangeTitle(callback) {
return this.emitter.on('did-change-title', callback)
}
onDidChangeModified (callback) {
onDidChangeModified(callback) {
// No op to suppress deprecation warning
return new Disposable()
}
onDidChangeMarkdown (callback) {
onDidChangeMarkdown(callback) {
return this.emitter.on('did-change-markdown', callback)
}
subscribeToFilePath (filePath) {
subscribeToFilePath(filePath) {
this.file = new File(filePath)
this.emitter.emit('did-change-title')
this.disposables.add(
@ -102,7 +102,7 @@ module.exports = class MarkdownPreviewView {
return this.renderMarkdown()
}
resolveEditor (editorId) {
resolveEditor(editorId) {
const resolve = () => {
this.editor = this.editorForId(editorId)
@ -127,7 +127,7 @@ module.exports = class MarkdownPreviewView {
}
}
editorForId (editorId) {
editorForId(editorId) {
for (const editor of atom.workspace.getTextEditors()) {
if (editor.id != null && editor.id.toString() === editorId.toString()) {
return editor
@ -136,7 +136,7 @@ module.exports = class MarkdownPreviewView {
return null
}
handleEvents () {
handleEvents() {
const lazyRenderMarkdown = _.debounce(() => this.renderMarkdown(), 250)
this.disposables.add(
atom.grammars.onDidAddGrammar(() => lazyRenderMarkdown())
@ -171,11 +171,11 @@ module.exports = class MarkdownPreviewView {
'markdown-preview:reset-zoom': () => {
this.element.style.zoom = 1
},
'markdown-preview:toggle-break-on-single-newline' () {
'markdown-preview:toggle-break-on-single-newline'() {
const keyPath = 'markdown-preview.breakOnSingleNewline'
atom.config.set(keyPath, !atom.config.get(keyPath))
},
'markdown-preview:toggle-github-style' () {
'markdown-preview:toggle-github-style'() {
const keyPath = 'markdown-preview.useGitHubStyle'
atom.config.set(keyPath, !atom.config.get(keyPath))
}
@ -226,10 +226,20 @@ module.exports = class MarkdownPreviewView {
)
)
this.disposables.add(
atom.config.observe('markdown-preview.gitHubStyleMode', gitHubStyleMode => {
this.gitHubStyleMode = gitHubStyleMode
if (this.useGitHubStyle) {
this.element.setAttribute('data-use-github-style', gitHubStyleMode)
}
})
)
this.disposables.add(
atom.config.observe('markdown-preview.useGitHubStyle', useGitHubStyle => {
this.useGitHubStyle = useGitHubStyle
if (useGitHubStyle) {
this.element.setAttribute('data-use-github-style', '')
this.element.setAttribute('data-use-github-style', this.gitHubStyleMode)
} else {
this.element.removeAttribute('data-use-github-style')
}
@ -253,7 +263,7 @@ module.exports = class MarkdownPreviewView {
}
}
renderMarkdown () {
renderMarkdown() {
if (!this.loaded) {
this.showLoading()
}
@ -266,7 +276,7 @@ module.exports = class MarkdownPreviewView {
.catch(reason => this.showError({ message: reason }))
}
getMarkdownSource () {
getMarkdownSource() {
if (this.file && this.file.getPath()) {
return this.file
.read()
@ -287,7 +297,7 @@ module.exports = class MarkdownPreviewView {
}
}
async getHTML () {
async getHTML() {
const source = await this.getMarkdownSource()
if (source == null) {
@ -297,7 +307,7 @@ module.exports = class MarkdownPreviewView {
return renderer.toHTML(source, this.getPath(), this.getGrammar())
}
async renderMarkdownText (text) {
async renderMarkdownText(text) {
const { scrollTop } = this.element
try {
@ -318,7 +328,7 @@ module.exports = class MarkdownPreviewView {
}
}
getTitle () {
getTitle() {
if (this.file != null && this.getPath() != null) {
return `${path.basename(this.getPath())} Preview`
} else if (this.editor != null) {
@ -328,11 +338,11 @@ module.exports = class MarkdownPreviewView {
}
}
getIconName () {
getIconName() {
return 'markdown'
}
getURI () {
getURI() {
if (this.file != null) {
return `markdown-preview://${this.getPath()}`
} else {
@ -340,7 +350,7 @@ module.exports = class MarkdownPreviewView {
}
}
getPath () {
getPath() {
if (this.file != null) {
return this.file.getPath()
} else if (this.editor != null) {
@ -348,16 +358,16 @@ module.exports = class MarkdownPreviewView {
}
}
getGrammar () {
getGrammar() {
return this.editor != null ? this.editor.getGrammar() : undefined
}
getDocumentStyleSheets () {
getDocumentStyleSheets() {
// This function exists so we can stub it
return document.styleSheets
}
getTextEditorStyles () {
getTextEditorStyles() {
const textEditorStyles = document.createElement('atom-styles')
textEditorStyles.initialize(atom.styles)
textEditorStyles.setAttribute('context', 'atom-text-editor')
@ -369,7 +379,7 @@ module.exports = class MarkdownPreviewView {
.map(styleElement => styleElement.innerText)
}
getMarkdownPreviewCSS () {
getMarkdownPreviewCSS() {
const markdownPreviewRules = []
const ruleRegExp = /\.markdown-preview/
const cssUrlRegExp = /url\(atom:\/\/markdown-preview\/assets\/(.*)\)/
@ -401,7 +411,7 @@ module.exports = class MarkdownPreviewView {
})
}
showError (result) {
showError(result) {
this.element.textContent = ''
const h2 = document.createElement('h2')
h2.textContent = 'Previewing Markdown Failed'
@ -413,7 +423,7 @@ module.exports = class MarkdownPreviewView {
}
}
showLoading () {
showLoading() {
this.loading = true
this.element.textContent = ''
const div = document.createElement('div')
@ -422,7 +432,7 @@ module.exports = class MarkdownPreviewView {
this.element.appendChild(div)
}
selectAll () {
selectAll() {
if (this.loading) {
return
}
@ -434,7 +444,7 @@ module.exports = class MarkdownPreviewView {
selection.addRange(range)
}
async copyToClipboard () {
async copyToClipboard() {
if (this.loading) {
return
}
@ -464,7 +474,7 @@ module.exports = class MarkdownPreviewView {
}
}
getSaveDialogOptions () {
getSaveDialogOptions() {
let defaultPath = this.getPath()
if (defaultPath) {
defaultPath += '.html'
@ -479,7 +489,7 @@ module.exports = class MarkdownPreviewView {
return { defaultPath }
}
async saveAs (htmlFilePath) {
async saveAs(htmlFilePath) {
if (this.loading) {
atom.notifications.addWarning(
'Please wait until the Markdown Preview has finished loading before saving'
@ -504,7 +514,7 @@ module.exports = class MarkdownPreviewView {
<title>${title}</title>
<style>${this.getMarkdownPreviewCSS()}</style>
</head>
<body class='markdown-preview' data-use-github-style>${htmlBody}</body>
<body class='markdown-preview' data-use-github-style="${this.gitHubStyleMode}">${htmlBody}</body>
</html>` + '\n' // Ensure trailing newline
fs.writeFileSync(htmlFilePath, html)

View File

@ -0,0 +1,651 @@
{
"name": "markdown-preview",
"version": "0.160.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "markdown-preview",
"version": "0.160.2",
"license": "MIT",
"dependencies": {
"cheerio": "^1.0.0-rc.3",
"dedent": "^1.5.3",
"dompurify": "^2.0.17",
"emoji-images": "^0.1.1",
"fs-plus": "^3.0.0",
"github-markdown-css": "^5.5.1",
"marked": "5.0.3",
"underscore-plus": "^1.0.0",
"yaml-front-matter": "^4.1.1"
},
"devDependencies": {
"temp": "^0.8.1"
},
"engines": {
"atom": "*"
}
},
"node_modules/@types/node": {
"version": "11.13.7",
"license": "MIT"
},
"node_modules/argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"dependencies": {
"sprintf-js": "~1.0.2"
}
},
"node_modules/async": {
"version": "1.5.2",
"license": "MIT"
},
"node_modules/balanced-match": {
"version": "1.0.0",
"license": "MIT"
},
"node_modules/boolbase": {
"version": "1.0.0",
"license": "ISC"
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/cheerio": {
"version": "1.0.0-rc.3",
"license": "MIT",
"dependencies": {
"css-select": "~1.2.0",
"dom-serializer": "~0.1.1",
"entities": "~1.1.1",
"htmlparser2": "^3.9.1",
"lodash": "^4.15.0",
"parse5": "^3.0.1"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/commander": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
"integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
"engines": {
"node": ">= 6"
}
},
"node_modules/concat-map": {
"version": "0.0.1",
"license": "MIT"
},
"node_modules/css-select": {
"version": "1.2.0",
"license": "BSD-like",
"dependencies": {
"boolbase": "~1.0.0",
"css-what": "2.1",
"domutils": "1.5.1",
"nth-check": "~1.0.1"
}
},
"node_modules/css-what": {
"version": "2.1.3",
"license": "BSD-2-Clause",
"engines": {
"node": "*"
}
},
"node_modules/dedent": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz",
"integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==",
"peerDependencies": {
"babel-plugin-macros": "^3.1.0"
},
"peerDependenciesMeta": {
"babel-plugin-macros": {
"optional": true
}
}
},
"node_modules/dom-serializer": {
"version": "0.1.1",
"license": "MIT",
"dependencies": {
"domelementtype": "^1.3.0",
"entities": "^1.1.1"
}
},
"node_modules/domelementtype": {
"version": "1.3.1",
"license": "BSD-2-Clause"
},
"node_modules/domhandler": {
"version": "2.4.2",
"license": "BSD-2-Clause",
"dependencies": {
"domelementtype": "1"
}
},
"node_modules/dompurify": {
"version": "2.4.7",
"license": "(MPL-2.0 OR Apache-2.0)"
},
"node_modules/domutils": {
"version": "1.5.1",
"dependencies": {
"dom-serializer": "0",
"domelementtype": "1"
}
},
"node_modules/emoji-images": {
"version": "0.1.1"
},
"node_modules/entities": {
"version": "1.1.2",
"license": "BSD-2-Clause"
},
"node_modules/esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"bin": {
"esparse": "bin/esparse.js",
"esvalidate": "bin/esvalidate.js"
},
"engines": {
"node": ">=4"
}
},
"node_modules/fs-plus": {
"version": "3.1.1",
"license": "MIT",
"dependencies": {
"async": "^1.5.2",
"mkdirp": "^0.5.1",
"rimraf": "^2.5.2",
"underscore-plus": "1.x"
}
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"license": "ISC"
},
"node_modules/github-markdown-css": {
"version": "5.5.1",
"resolved": "https://registry.npmjs.org/github-markdown-css/-/github-markdown-css-5.5.1.tgz",
"integrity": "sha512-2osyhNgFt7DEHnGHbgIifWawAqlc68gjJiGwO1xNw/S48jivj8kVaocsVkyJqUi3fm7fdYIDi4C6yOtcqR/aEQ==",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/glob": {
"version": "7.1.3",
"license": "ISC",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
}
},
"node_modules/htmlparser2": {
"version": "3.10.1",
"license": "MIT",
"dependencies": {
"domelementtype": "^1.3.1",
"domhandler": "^2.3.0",
"domutils": "^1.5.1",
"entities": "^1.1.1",
"inherits": "^2.0.1",
"readable-stream": "^3.1.1"
}
},
"node_modules/inflight": {
"version": "1.0.6",
"license": "ISC",
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"node_modules/inherits": {
"version": "2.0.3",
"license": "ISC"
},
"node_modules/js-yaml": {
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
"dependencies": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/lodash": {
"version": "4.17.21",
"license": "MIT"
},
"node_modules/marked": {
"version": "5.0.3",
"license": "MIT",
"bin": {
"marked": "bin/marked.js"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/minimatch": {
"version": "3.0.4",
"license": "ISC",
"dependencies": {
"brace-expansion": "^1.1.7"
},
"engines": {
"node": "*"
}
},
"node_modules/minimist": {
"version": "0.0.8",
"license": "MIT"
},
"node_modules/mkdirp": {
"version": "0.5.1",
"license": "MIT",
"dependencies": {
"minimist": "0.0.8"
},
"bin": {
"mkdirp": "bin/cmd.js"
}
},
"node_modules/nth-check": {
"version": "1.0.2",
"license": "BSD-2-Clause",
"dependencies": {
"boolbase": "~1.0.0"
}
},
"node_modules/once": {
"version": "1.4.0",
"license": "ISC",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/parse5": {
"version": "3.0.3",
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/path-is-absolute": {
"version": "1.0.1",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/readable-stream": {
"version": "3.3.0",
"license": "MIT",
"dependencies": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/rimraf": {
"version": "2.6.3",
"license": "ISC",
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
}
},
"node_modules/safe-buffer": {
"version": "5.1.2",
"license": "MIT"
},
"node_modules/sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
},
"node_modules/string_decoder": {
"version": "1.2.0",
"license": "MIT",
"dependencies": {
"safe-buffer": "~5.1.0"
}
},
"node_modules/temp": {
"version": "0.8.4",
"dev": true,
"license": "MIT",
"dependencies": {
"rimraf": "~2.6.2"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/underscore": {
"version": "1.13.1",
"license": "MIT"
},
"node_modules/underscore-plus": {
"version": "1.7.0",
"dependencies": {
"underscore": "^1.9.1"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"license": "MIT"
},
"node_modules/wrappy": {
"version": "1.0.2",
"license": "ISC"
},
"node_modules/yaml-front-matter": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/yaml-front-matter/-/yaml-front-matter-4.1.1.tgz",
"integrity": "sha512-ULGbghCLsN8Hs8vfExlqrJIe8Hl2TUjD7/zsIGMP8U+dgRXEsDXk4yydxeZJgdGiimP1XB7zhmhOB4/HyfqOyQ==",
"dependencies": {
"commander": "^6.2.0",
"js-yaml": "^3.14.1"
},
"bin": {
"yaml-front-matter": "bin/js-yaml-front.js"
}
}
},
"dependencies": {
"@types/node": {
"version": "11.13.7"
},
"argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"requires": {
"sprintf-js": "~1.0.2"
}
},
"async": {
"version": "1.5.2"
},
"balanced-match": {
"version": "1.0.0"
},
"boolbase": {
"version": "1.0.0"
},
"brace-expansion": {
"version": "1.1.11",
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"cheerio": {
"version": "1.0.0-rc.3",
"requires": {
"css-select": "~1.2.0",
"dom-serializer": "~0.1.1",
"entities": "~1.1.1",
"htmlparser2": "^3.9.1",
"lodash": "^4.15.0",
"parse5": "^3.0.1"
}
},
"commander": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
"integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA=="
},
"concat-map": {
"version": "0.0.1"
},
"css-select": {
"version": "1.2.0",
"requires": {
"boolbase": "~1.0.0",
"css-what": "2.1",
"domutils": "1.5.1",
"nth-check": "~1.0.1"
}
},
"css-what": {
"version": "2.1.3"
},
"dedent": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz",
"integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==",
"requires": {}
},
"dom-serializer": {
"version": "0.1.1",
"requires": {
"domelementtype": "^1.3.0",
"entities": "^1.1.1"
}
},
"domelementtype": {
"version": "1.3.1"
},
"domhandler": {
"version": "2.4.2",
"requires": {
"domelementtype": "1"
}
},
"dompurify": {
"version": "2.4.7"
},
"domutils": {
"version": "1.5.1",
"requires": {
"dom-serializer": "0",
"domelementtype": "1"
}
},
"emoji-images": {
"version": "0.1.1"
},
"entities": {
"version": "1.1.2"
},
"esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
},
"fs-plus": {
"version": "3.1.1",
"requires": {
"async": "^1.5.2",
"mkdirp": "^0.5.1",
"rimraf": "^2.5.2",
"underscore-plus": "1.x"
}
},
"fs.realpath": {
"version": "1.0.0"
},
"github-markdown-css": {
"version": "5.5.1",
"resolved": "https://registry.npmjs.org/github-markdown-css/-/github-markdown-css-5.5.1.tgz",
"integrity": "sha512-2osyhNgFt7DEHnGHbgIifWawAqlc68gjJiGwO1xNw/S48jivj8kVaocsVkyJqUi3fm7fdYIDi4C6yOtcqR/aEQ=="
},
"glob": {
"version": "7.1.3",
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"htmlparser2": {
"version": "3.10.1",
"requires": {
"domelementtype": "^1.3.1",
"domhandler": "^2.3.0",
"domutils": "^1.5.1",
"entities": "^1.1.1",
"inherits": "^2.0.1",
"readable-stream": "^3.1.1"
}
},
"inflight": {
"version": "1.0.6",
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.3"
},
"js-yaml": {
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
"requires": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
}
},
"lodash": {
"version": "4.17.21"
},
"marked": {
"version": "5.0.3"
},
"minimatch": {
"version": "3.0.4",
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "0.0.8"
},
"mkdirp": {
"version": "0.5.1",
"requires": {
"minimist": "0.0.8"
}
},
"nth-check": {
"version": "1.0.2",
"requires": {
"boolbase": "~1.0.0"
}
},
"once": {
"version": "1.4.0",
"requires": {
"wrappy": "1"
}
},
"parse5": {
"version": "3.0.3",
"requires": {
"@types/node": "*"
}
},
"path-is-absolute": {
"version": "1.0.1"
},
"readable-stream": {
"version": "3.3.0",
"requires": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
}
},
"rimraf": {
"version": "2.6.3",
"requires": {
"glob": "^7.1.3"
}
},
"safe-buffer": {
"version": "5.1.2"
},
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
},
"string_decoder": {
"version": "1.2.0",
"requires": {
"safe-buffer": "~5.1.0"
}
},
"temp": {
"version": "0.8.4",
"dev": true,
"requires": {
"rimraf": "~2.6.2"
}
},
"underscore": {
"version": "1.13.1"
},
"underscore-plus": {
"version": "1.7.0",
"requires": {
"underscore": "^1.9.1"
}
},
"util-deprecate": {
"version": "1.0.2"
},
"wrappy": {
"version": "1.0.2"
},
"yaml-front-matter": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/yaml-front-matter/-/yaml-front-matter-4.1.1.tgz",
"integrity": "sha512-ULGbghCLsN8Hs8vfExlqrJIe8Hl2TUjD7/zsIGMP8U+dgRXEsDXk4yydxeZJgdGiimP1XB7zhmhOB4/HyfqOyQ==",
"requires": {
"commander": "^6.2.0",
"js-yaml": "^3.14.1"
}
}
}
}

View File

@ -8,11 +8,16 @@
"engines": {
"atom": "*"
},
"scripts": {
"generate-github-markdown-css": "node scripts/generate-github-markdown-css.js"
},
"dependencies": {
"cheerio": "^1.0.0-rc.3",
"dedent": "^1.5.3",
"dompurify": "^2.0.17",
"emoji-images": "^0.1.1",
"fs-plus": "^3.0.0",
"github-markdown-css": "^5.5.1",
"marked": "5.0.3",
"underscore-plus": "^1.0.0",
"yaml-front-matter": "^4.1.1"
@ -26,25 +31,30 @@
"configSchema": {
"breakOnSingleNewline": {
"type": "boolean",
"order": 1,
"default": false,
"description": "In Markdown, a single newline character doesn't cause a line break in the generated HTML. In GitHub Flavored Markdown, that is not true. Enable this config option to insert line breaks in rendered HTML for single newlines in Markdown source."
},
"liveUpdate": {
"type": "boolean",
"order": 2,
"default": true,
"description": "Re-render the preview as the contents of the source changes, without requiring the source buffer to be saved. If disabled, the preview is re-rendered only when the buffer is saved to disk."
},
"openPreviewInSplitPane": {
"order": 3,
"type": "boolean",
"default": true,
"description": "Open the preview in a split pane. If disabled, the preview is opened in a new tab in the same pane."
},
"allowUnsafeProtocols": {
"order": 4,
"type": "boolean",
"default": false,
"description": "Allow HTML attributes to use protocols normally considered unsafe such as `file://` and absolute paths on Windows."
},
"grammars": {
"order": 0,
"type": "array",
"default": [
"source.gfm",
@ -57,12 +67,36 @@
"description": "List of scopes for languages for which previewing is enabled. See [this README](https://github.com/pulsar-edit/spell-check#readme) for more information on finding the correct scope for a specific language."
},
"useGitHubStyle": {
"title": "Use GitHub.com style",
"order": 5,
"title": "Use GitHub.com Style",
"type": "boolean",
"default": false,
"description": "Use the same CSS styles for preview as the ones used on GitHub.com."
},
"gitHubStyleMode": {
"order": 6,
"title": "GitHub.com Style Mode",
"type": "string",
"default": "auto",
"description": "Whether to use light-mode GitHub CSS, dark-mode GitHub CSS, or system default (based on your operating system preferences). Has no effect unless **Use GitHub.com Style** is enabled.",
"enum": [
{
"value": "auto",
"description": "System Default"
},
{
"value": "light",
"description": "Light"
},
{
"value": "dark",
"description": "Dark"
}
]
},
"syntaxHighlightingLanguageIdentifier": {
"order": 7,
"title": "Syntax Highlighting Language Identifiers",
"description": "Syntax Highlighting System to use for code block language identification. See [the README](https://github.com/pulsar-edit/pulsar/tree/master/packages/markdown-preview#readme) for details.",
"type": "string",
"default": "linguist",
@ -86,14 +120,14 @@
]
},
"customSyntaxHighlightingLanguageIdentifiers": {
"description": "Custom comma seperated list of Syntax Language Identifiers to map to any language. See [the README](https://github.com/pulsar-edit/pulsar/tree/master/packages/markdown-preview#readme) for usage.",
"description": "Comma-separated list of syntax language identifiers to map to any language. See [the README](https://github.com/pulsar-edit/pulsar/tree/master/packages/markdown-preview#readme) for usage.",
"type": "string",
"default": ""
},
"useOriginalParser": {
"description": "Wether to use the original Markdown Parser, or the new Pulsar one.",
"description": "When checked, will use the original Markdown parser for `markdown-preview` (`marked`). When unchecked, will use the new Markdown parser built into Pulsar (`markdown-it`).",
"type": "boolean",
"default": "true"
"default": true
}
}
}

View File

@ -0,0 +1,38 @@
// Run this script whenever the `github-markdown-css` dependency is updated in
// order to regenerate GitHub styles.
const fs = require('fs/promises');
const path = require('path');
const dedent = require('dedent');
const ASSETS = path.resolve(__dirname, '..', 'assets')
const ASSET_LIGHT = require.resolve('github-markdown-css/github-markdown-light.css')
const ASSET_DARK = require.resolve('github-markdown-css/github-markdown-dark.css')
async function run() {
let lightContents = (await fs.readFile(ASSET_LIGHT)).toString();
let darkContents = (await fs.readFile(ASSET_DARK)).toString();
let lightCSSAuto = lightContents.replace(/\.markdown-body\b/g, '.markdown-preview[data-use-github-style="auto"]');
let darkCSSAuto = darkContents.replace(/\.markdown-body\b/g, '.markdown-preview[data-use-github-style="auto"]');
const autoCSSMode = dedent`
@media (prefers-color-scheme: light) {
${lightCSSAuto}
}
@media (prefers-color-scheme: dark) {
${darkCSSAuto}
}
`;
let lightCSSMode = lightContents.replace(/\.markdown-body\b/g, '.markdown-preview[data-use-github-style="light"]');
let darkCSSMode = darkContents.replace(/\.markdown-body\b/g, '.markdown-preview[data-use-github-style="dark"]');
await fs.writeFile(path.join(ASSETS, 'github-markdown-auto.css'), autoCSSMode);
await fs.writeFile(path.join(ASSETS, 'github-markdown-light.css'), lightCSSMode);
await fs.writeFile(path.join(ASSETS, 'github-markdown-dark.css'), darkCSSMode);
}
run()

View File

@ -0,0 +1,12 @@
{
"env": { "jasmine": true },
"rules": {
"node/no-unpublished-require": "off",
"node/no-extraneous-require": "off",
"no-unused-vars": "off",
"no-empty": "off"
},
"globals": {
"waitsForPromise": true
}
}

View File

@ -722,7 +722,7 @@ world\
expectPreviewInSplitPane()
runs(() =>
expect(preview.element.getAttribute('data-use-github-style')).toBe('')
expect(preview.element.getAttribute('data-use-github-style')).toBe('auto')
)
})

View File

@ -601,4 +601,39 @@ enc\
})
})
})
describe('when GitHub styles are enabled', () => {
beforeEach(() => {
atom.config.set('markdown-preview.useGitHubStyle', true)
atom.config.set('markdown-preview.gitHubStyleMode', 'light')
})
it('uses the GitHub styles', () => {
jasmine.attachToDOM(preview.element)
// It's possible that these values will need to change when the GitHub
// CSS is updated.
const expectedColors = {
light: `rgb(31, 35, 40)`,
dark: `rgb(230, 237, 243)`
}
waitsForPromise(() => preview.renderMarkdown())
// Perform some basic sanity checks about these modes.
expect(preview.element.dataset.useGithubStyle).toBe('light')
let paragraph = preview.element.querySelector('p')
expect(getComputedStyle(paragraph).color).toBe(expectedColors.light)
atom.config.set('markdown-preview.gitHubStyleMode', 'dark')
expect(preview.element.dataset.useGithubStyle).toBe('dark')
expect(getComputedStyle(paragraph).color).toBe(expectedColors.dark)
atom.config.set('markdown-preview.gitHubStyleMode', 'auto')
expect(preview.element.dataset.useGithubStyle).toBe('auto')
// We don't know which mode will be preferred on the system we're running
// on, but as a sanity check we can at least verify that the style value
// is one of the two values we just asserted.
expect([expectedColors.light, expectedColors.dark]).toContain(getComputedStyle(paragraph).color)
})
})
})

View File

@ -1,33 +1,44 @@
// GitHub.com styles
// These are the GitHub Flavored Markdown styles also found on github.com.
// They can be anabled in the markdown-preview settings by turning on "Use GitHub.com styles".
// These are the GitHub Flavored Markdown styles also found on github.com. They
// can be enabled in the `markdown-preview` settings by turning on "Use
// GitHub.com Styles."
//
// We define styles for both dark mode and light mode. A specific mode can be
// opted into via the “GitHub.com Style Mode” setting… or else the user can
// leave the setting on “System Default” to use whatever mode the OS has
// decided to use.
@import (reference) "../assets/primer-markdown";
// The GitHub styles are imported from the `github-markdown-css` package, then
// customized via the `generate-github-markdown-css` task and written to the
// `assets` directory. The task applies some simple transformations to the CSS
// and handles the light-mode/dark-mode logic.
//
// We import these files as `less` files (even though they're ordinary CSS)
// because that forces Less to process them instead of leaving them for the
// standard `@import` directive in CSS. Less can resolve these relative paths,
// but CSS can't.
@import (less) "../assets/github-markdown-auto.css";
@import (less) "../assets/github-markdown-light.css";
@import (less) "../assets/github-markdown-dark.css";
.markdown-preview[data-use-github-style] {
// After we import these rules, we define some overrides; these are needed
// because some UI theme style rules could bleed into Markdown preview areas in
// situations where GitHub relies on browser defaults or fails to envision the
// presence of other possible style rules. Since we don't know what rules the
// user's UI theme has defined, we need to be a bit more paranoid.
// Includes GitHub.com styles from `../assets/primer-markdown.less`.
// Source: https://github.com/primer/primer/tree/master/modules/primer-markdown
.markdown-body();
// The styles below override/complement the GitHub.com styles
// It's needed because some markup or global styles are different
// Overrides for all themes.
.markdown-preview-additions() {
padding: 30px;
font-size: 16px;
color: #333;
background-color: #fff;
overflow: scroll;
a {
color: #337ab7;
}
code {
color: inherit;
border: inherit;
}
atom-text-editor {
@ -37,4 +48,45 @@
border-radius: 4px;
overflow: auto;
}
}
// Overrides for dark mode.
.markdown-preview-additions-dark() {
.markdown-preview-additions();
color: rgb(230, 237, 243);
background-color: rgb(13, 17, 23);
a {
color: rgb(69, 147, 248);
}
}
// Overrides for light mode.
.markdown-preview-additions-light() {
.markdown-preview-additions();
color: rgb(31, 35, 40);
background-color: rgb(255, 255, 255);
a {
color: rgb(11, 105, 218);
}
}
.markdown-preview[data-use-github-style="light"] {
.markdown-preview-additions-light();
}
@media (prefers-color-scheme: light) {
.markdown-preview[data-use-github-style="auto"] {
.markdown-preview-additions-light();
}
}
.markdown-preview[data-use-github-style="dark"] {
.markdown-preview-additions-dark();
}
@media (prefers-color-scheme: dark) {
.markdown-preview[data-use-github-style="auto"] {
.markdown-preview-additions-dark();
}
}