feat: work on highlighting and displaying language snippets

This commit is contained in:
Stevan Freeborn
2023-04-11 22:45:48 -05:00
parent c87b2a39e8
commit 5f4d4f656e
8 changed files with 202 additions and 27 deletions
@@ -20,6 +20,7 @@
overflow: auto; overflow: auto;
padding: 1rem; padding: 1rem;
scrollbar-color: #043160 #0b3766; scrollbar-color: #043160 #0b3766;
max-height: calc(100vh - 280px);
} }
.snippetContent>pre::-webkit-scrollbar { .snippetContent>pre::-webkit-scrollbar {
@@ -1,13 +1,14 @@
'use client'; 'use client';
import Prism from 'prismjs'; import {
import 'prismjs/components/prism-json'; Children,
import 'prismjs/themes/prism.css'; MouseEvent,
ReactElement,
useState,
} from 'react';
import styles from './CodeSnippet.module.css';
import { MouseEvent, useEffect, useState } from 'react'; function CodeSnippetCopyButton() {
import styles from './Code.module.css';
function CodeCopyButton() {
const [copyButtonTooltip, setCopyButtonTooltip] = const [copyButtonTooltip, setCopyButtonTooltip] =
useState<boolean>(false); useState<boolean>(false);
@@ -65,27 +66,42 @@ function CodeCopyButton() {
); );
} }
export default function Code({ function SnippetLanguageDropdown() {}
export default function CodeSnippet({
children, children,
language,
heading, heading,
defaultLanguage,
}: { }: {
children: string; children: ReactElement;
language: string;
heading: string; heading: string;
defaultLanguage: string;
}) { }) {
useEffect(() => { const [selectedLanguage, setSelectedLanguage] =
Prism.highlightAll(); useState<string>(defaultLanguage);
}, []);
const snippetLanguages = Children.toArray(children).map(
(child: any) => child.props.className.split('-')[1]
);
return ( return (
<div className={styles.snippetContainer}> <div className={styles.snippetContainer}>
<div className={styles.snippetHeader}> <div className={styles.snippetHeader}>
<div>{heading}</div> <div>{heading}</div>
<CodeCopyButton /> <CodeSnippetCopyButton />
</div> </div>
<div className={styles.snippetContent}> <div className={styles.snippetContent}>
{children} <pre>
{Children.toArray(children)
.filter(
(child: any) =>
child.props.className ===
`language-${defaultLanguage}`
)
.map(child => {
return child;
})}
</pre>
</div> </div>
</div> </div>
); );
+24
View File
@@ -0,0 +1,24 @@
import Prism from 'prismjs';
import 'prismjs/components/prism-bash';
import 'prismjs/components/prism-json';
import './prism-custom.css';
export default function Fence({
content,
language,
}: {
content: string;
language: string;
}) {
const html = Prism.highlight(
content,
Prism.languages[language],
language
);
return (
<code
className={`language-${language}`}
dangerouslySetInnerHTML={{ __html: html }}
></code>
);
}
+115
View File
@@ -0,0 +1,115 @@
code[class*="language-"],
pre[class*="language-"] {
color: #f8f8f2;
background: none;
text-shadow: 0 1px rgba(0, 0, 0, 0.3);
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
border-radius: 0.3em;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #282a36;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #6272a4;
}
.token.punctuation {
color: #f8f8f2;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.constant,
.token.symbol,
.token.deleted {
color: #ff79c6;
}
.token.boolean,
.token.number {
color: #bd93f9;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #50fa7b;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string,
.token.variable {
color: #f8f8f2;
}
.token.atrule,
.token.attr-value,
.token.function,
.token.class-name {
color: #f1fa8c;
}
.token.keyword {
color: #8be9fd;
}
.token.regex,
.token.important {
color: #ffb86c;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
+20 -5
View File
@@ -2,7 +2,8 @@ import { default as Markdoc } from '@markdoc/markdoc';
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import React, { ReactNode } from 'react'; import React, { ReactNode } from 'react';
import Code from '../components/Code'; import CodeSnippet from '../components/CodeSnippet';
import Fence from '../components/Fence';
import { Doc, DocSection } from './../types/types'; import { Doc, DocSection } from './../types/types';
const DOCS_PATH = path.join(process.cwd(), 'src/docs'); const DOCS_PATH = path.join(process.cwd(), 'src/docs');
@@ -34,16 +35,29 @@ function getExamplePath(version: string, doc: Doc): string {
} }
const markDocConfig = { const markDocConfig = {
tags: { nodes: {
code: { fence: {
render: 'Code', render: 'Fence',
attributes: { attributes: {
language: { language: {
type: 'string', type: 'string',
}, },
content: {
type: 'string',
},
},
},
},
tags: {
code: {
render: 'CodeSnippet',
attributes: {
heading: { heading: {
type: 'string', type: 'string',
}, },
defaultLanguage: {
type: 'string',
},
}, },
}, },
}, },
@@ -58,7 +72,8 @@ function parseMarkdown(sourcePath: string): ReactNode {
); );
const children = Markdoc.renderers.react(content, React, { const children = Markdoc.renderers.react(content, React, {
components: { components: {
Code: Code, CodeSnippet: CodeSnippet,
Fence: Fence,
}, },
}); });
@@ -2,7 +2,7 @@
API Keys are specific to an instance. If you are using the API to access data from multiple instances, you will need to create an API key for each instance. API Keys are specific to an instance. If you are using the API to access data from multiple instances, you will need to create an API key for each instance.
{% code heading="X-API KEY" language="text" %} {% code heading="X-API KEY" defaultLanguage="text" %}
```text ```text
X-ApiKey: 000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000 X-ApiKey: 000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000
+1 -1
View File
@@ -2,7 +2,7 @@
The base url for the Onspring API will be the same for all instances regardless of whether the instances is a development, test, or production instance. The base url for the Onspring API will be the same for all instances regardless of whether the instances is a development, test, or production instance.
{% code heading="BASE URL" language="text" %} {% code heading="BASE URL" defaultLanguage="text" %}
```text ```text
https://api.onspring.com https://api.onspring.com
@@ -1,15 +1,19 @@
{% code heading="GET /Records/appId/{appID}" language="text" %} {% code heading="GET /Records/appId/{appID}" defaultLanguage="bash" %}
```curl ```bash
curl --location 'https://api.onspring.com/Records/appId/195' \ curl --location 'https://api.onspring.com/Records/appId/195' \
--header 'X-ApiKey: 000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000' --header 'X-ApiKey: 000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000'
``` ```
```js
var request = require('request');
```
{% /code %} {% /code %}
{% code heading="RESPONSE" language="json" %} {% code heading="RESPONSE" defaultLanguage="json" %}
```json {% .language-json %} ```json
{ {
"pageNumber": 1, "pageNumber": 1,
"pageSize": 1, "pageSize": 1,