diff --git a/src/app/components/Code.module.css b/src/app/components/CodeSnippet.module.css similarity index 97% rename from src/app/components/Code.module.css rename to src/app/components/CodeSnippet.module.css index 7bdcbe0..6a99217 100644 --- a/src/app/components/Code.module.css +++ b/src/app/components/CodeSnippet.module.css @@ -20,6 +20,7 @@ overflow: auto; padding: 1rem; scrollbar-color: #043160 #0b3766; + max-height: calc(100vh - 280px); } .snippetContent>pre::-webkit-scrollbar { diff --git a/src/app/components/Code.tsx b/src/app/components/CodeSnippet.tsx similarity index 69% rename from src/app/components/Code.tsx rename to src/app/components/CodeSnippet.tsx index d56aa5d..67140fb 100644 --- a/src/app/components/Code.tsx +++ b/src/app/components/CodeSnippet.tsx @@ -1,13 +1,14 @@ 'use client'; -import Prism from 'prismjs'; -import 'prismjs/components/prism-json'; -import 'prismjs/themes/prism.css'; +import { + Children, + MouseEvent, + ReactElement, + useState, +} from 'react'; +import styles from './CodeSnippet.module.css'; -import { MouseEvent, useEffect, useState } from 'react'; -import styles from './Code.module.css'; - -function CodeCopyButton() { +function CodeSnippetCopyButton() { const [copyButtonTooltip, setCopyButtonTooltip] = useState(false); @@ -65,27 +66,42 @@ function CodeCopyButton() { ); } -export default function Code({ +function SnippetLanguageDropdown() {} + +export default function CodeSnippet({ children, - language, heading, + defaultLanguage, }: { - children: string; - language: string; + children: ReactElement; heading: string; + defaultLanguage: string; }) { - useEffect(() => { - Prism.highlightAll(); - }, []); + const [selectedLanguage, setSelectedLanguage] = + useState(defaultLanguage); + + const snippetLanguages = Children.toArray(children).map( + (child: any) => child.props.className.split('-')[1] + ); return (
{heading}
- +
- {children} +
+          {Children.toArray(children)
+            .filter(
+              (child: any) =>
+                child.props.className ===
+                `language-${defaultLanguage}`
+            )
+            .map(child => {
+              return child;
+            })}
+        
); diff --git a/src/app/components/Fence.tsx b/src/app/components/Fence.tsx new file mode 100644 index 0000000..ecbfb3c --- /dev/null +++ b/src/app/components/Fence.tsx @@ -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 ( + + ); +} diff --git a/src/app/components/prism-custom.css b/src/app/components/prism-custom.css new file mode 100644 index 0000000..44aedd0 --- /dev/null +++ b/src/app/components/prism-custom.css @@ -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; +} \ No newline at end of file diff --git a/src/app/lib/markdoc.ts b/src/app/lib/markdoc.ts index 57eb9ab..1f40bbd 100644 --- a/src/app/lib/markdoc.ts +++ b/src/app/lib/markdoc.ts @@ -2,7 +2,8 @@ import { default as Markdoc } from '@markdoc/markdoc'; import fs from 'fs'; import path from 'path'; 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'; const DOCS_PATH = path.join(process.cwd(), 'src/docs'); @@ -34,16 +35,29 @@ function getExamplePath(version: string, doc: Doc): string { } const markDocConfig = { - tags: { - code: { - render: 'Code', + nodes: { + fence: { + render: 'Fence', attributes: { language: { type: 'string', }, + content: { + type: 'string', + }, + }, + }, + }, + tags: { + code: { + render: 'CodeSnippet', + attributes: { heading: { type: 'string', }, + defaultLanguage: { + type: 'string', + }, }, }, }, @@ -58,7 +72,8 @@ function parseMarkdown(sourcePath: string): ReactNode { ); const children = Markdoc.renderers.react(content, React, { components: { - Code: Code, + CodeSnippet: CodeSnippet, + Fence: Fence, }, }); diff --git a/src/docs/version_002/authentication/example.md b/src/docs/version_002/authentication/example.md index 596a1b9..86559cf 100644 --- a/src/docs/version_002/authentication/example.md +++ b/src/docs/version_002/authentication/example.md @@ -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. -{% code heading="X-API KEY" language="text" %} +{% code heading="X-API KEY" defaultLanguage="text" %} ```text X-ApiKey: 000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000 diff --git a/src/docs/version_002/introduction/example.md b/src/docs/version_002/introduction/example.md index 6288694..2b83cef 100644 --- a/src/docs/version_002/introduction/example.md +++ b/src/docs/version_002/introduction/example.md @@ -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. -{% code heading="BASE URL" language="text" %} +{% code heading="BASE URL" defaultLanguage="text" %} ```text https://api.onspring.com diff --git a/src/docs/version_002/resources/records/get_records_by_app/example.md b/src/docs/version_002/resources/records/get_records_by_app/example.md index 21e3a71..3c9d74b 100644 --- a/src/docs/version_002/resources/records/get_records_by_app/example.md +++ b/src/docs/version_002/resources/records/get_records_by_app/example.md @@ -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' \ --header 'X-ApiKey: 000000ffffff000000ffffff/00000000-ffff-0000-ffff-000000000000' ``` +```js +var request = require('request'); +``` + {% /code %} -{% code heading="RESPONSE" language="json" %} +{% code heading="RESPONSE" defaultLanguage="json" %} -```json {% .language-json %} +```json { "pageNumber": 1, "pageSize": 1,