mirror of
https://github.com/explosion/spaCy.git
synced 2025-01-27 17:54:39 +03:00
Fix code syntax highlighting
This commit is contained in:
parent
46fb76c281
commit
47e4c62741
4947
website/package-lock.json
generated
4947
website/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
@ -11,6 +11,7 @@
|
||||||
"prettier": "prettier . --write"
|
"prettier": "prettier . --write"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@mapbox/rehype-prism": "^0.8.0",
|
||||||
"@mdx-js/loader": "^2.1.5",
|
"@mdx-js/loader": "^2.1.5",
|
||||||
"@mdx-js/react": "^2.1.5",
|
"@mdx-js/react": "^2.1.5",
|
||||||
"@next/mdx": "^13.0.2",
|
"@next/mdx": "^13.0.2",
|
||||||
|
@ -18,6 +19,7 @@
|
||||||
"@types/node": "18.11.9",
|
"@types/node": "18.11.9",
|
||||||
"@types/react": "18.0.25",
|
"@types/react": "18.0.25",
|
||||||
"@types/react-dom": "18.0.8",
|
"@types/react-dom": "18.0.8",
|
||||||
|
"acorn": "^8.8.1",
|
||||||
"browser-monads": "^1.0.0",
|
"browser-monads": "^1.0.0",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
"eslint": "8.27.0",
|
"eslint": "8.27.0",
|
||||||
|
@ -27,7 +29,9 @@
|
||||||
"md-attr-parser": "^1.3.0",
|
"md-attr-parser": "^1.3.0",
|
||||||
"next": "13.0.2",
|
"next": "13.0.2",
|
||||||
"next-mdx-remote": "^4.2.0",
|
"next-mdx-remote": "^4.2.0",
|
||||||
|
"parse-numeric-range": "^1.3.0",
|
||||||
"prettier": "^2.7.1",
|
"prettier": "^2.7.1",
|
||||||
|
"prismjs": "^1.29.0",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
|
|
|
@ -92,9 +92,7 @@ export const getStaticProps: GetStaticProps<PropsPage, ParsedUrlQuery> = async (
|
||||||
|
|
||||||
const mdx = await serialize(fs.readFileSync(pathFileWithIndexAndExtension, 'utf-8'), {
|
const mdx = await serialize(fs.readFileSync(pathFileWithIndexAndExtension, 'utf-8'), {
|
||||||
parseFrontmatter: true,
|
parseFrontmatter: true,
|
||||||
mdxOptions: {
|
mdxOptions: { remarkPlugins },
|
||||||
remarkPlugins,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!mdx.frontmatter) {
|
if (!mdx.frontmatter) {
|
||||||
|
|
|
@ -17,7 +17,8 @@ const getProps = (estree) => {
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
const estreeBodyFirstNode = estree.body[0]
|
const estreeBodyFirstNode =
|
||||||
|
estree.body[0].type === 'BlockStatement' ? estree.body[0].body[0] : estree.body[0]
|
||||||
|
|
||||||
if (estreeBodyFirstNode.type !== 'ExpressionStatement' || !estreeBodyFirstNode.expression) {
|
if (estreeBodyFirstNode.type !== 'ExpressionStatement' || !estreeBodyFirstNode.expression) {
|
||||||
return {}
|
return {}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
/**
|
/**
|
||||||
* Support titles, line highlights and more for code blocks
|
* Support titles, line highlights and more for code blocks
|
||||||
*/
|
*/
|
||||||
|
import { Parser } from 'acorn'
|
||||||
import { visit } from 'unist-util-visit'
|
import { visit } from 'unist-util-visit'
|
||||||
import parseAttr from 'md-attr-parser'
|
import parseAttr from 'md-attr-parser'
|
||||||
|
|
||||||
|
import getProps from './getProps.mjs'
|
||||||
|
|
||||||
const defaultOptions = {
|
const defaultOptions = {
|
||||||
defaultPrefix: '###',
|
defaultPrefix: '###',
|
||||||
prefixMap: {
|
prefixMap: {
|
||||||
|
@ -43,12 +45,15 @@ function remarkCodeBlocks(userOptions = {}) {
|
||||||
firstLine.startsWith('%%GITHUB_')
|
firstLine.startsWith('%%GITHUB_')
|
||||||
) {
|
) {
|
||||||
// GitHub URL
|
// GitHub URL
|
||||||
attrs.github = 'true'
|
attrs.github = node.value
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = node.data || (node.data = {})
|
const data = node.data || (node.data = {})
|
||||||
const hProps = data.hProperties || (data.hProperties = {})
|
const hProps = data.hProperties || (data.hProperties = {})
|
||||||
node.data.hProperties = Object.assign({}, hProps, attrs)
|
|
||||||
|
const meta = getProps(Parser.parse(node.meta, { ecmaVersion: 'latest' }))
|
||||||
|
|
||||||
|
node.data.hProperties = Object.assign({}, hProps, attrs, meta)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,18 @@
|
||||||
import React, { Fragment } from 'react'
|
import React, { Fragment, useEffect, useState } from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import highlightCode from 'gatsby-remark-prismjs/highlight-code.js'
|
|
||||||
import 'prismjs-bibtex'
|
|
||||||
import rangeParser from 'parse-numeric-range'
|
import rangeParser from 'parse-numeric-range'
|
||||||
import { window } from 'browser-monads'
|
import Prism from 'prismjs'
|
||||||
|
|
||||||
|
// We manually load all the languages that are needed, which are currently only those:
|
||||||
|
import 'prismjs/components/prism-diff.min.js'
|
||||||
|
import 'prismjs/components/prism-bash.min.js'
|
||||||
|
import 'prismjs/components/prism-ini.min.js'
|
||||||
|
import 'prismjs/components/prism-jsx.min.js'
|
||||||
|
import 'prismjs/components/prism-json.min.js'
|
||||||
|
import 'prismjs/components/prism-markdown.min.js'
|
||||||
|
import 'prismjs/components/prism-python.min.js'
|
||||||
|
import 'prismjs/components/prism-yaml.min.js'
|
||||||
|
|
||||||
import CUSTOM_TYPES from '../../meta/type-annotations.json'
|
import CUSTOM_TYPES from '../../meta/type-annotations.json'
|
||||||
import { isString, htmlToReact } from './util'
|
import { isString, htmlToReact } from './util'
|
||||||
|
@ -71,7 +79,8 @@ export const TypeAnnotation = ({ lang = 'python', link = true, children }) => {
|
||||||
const code = Array.isArray(children) ? children.join('') : children || ''
|
const code = Array.isArray(children) ? children.join('') : children || ''
|
||||||
const [rawText, meta] = code.split(/(?= \(.+\)$)/)
|
const [rawText, meta] = code.split(/(?= \(.+\)$)/)
|
||||||
const rawStr = rawText.replace(/\./g, TMP_DOT)
|
const rawStr = rawText.replace(/\./g, TMP_DOT)
|
||||||
const rawHtml = lang === 'none' || !code ? code : highlightCode(lang, rawStr)
|
const rawHtml =
|
||||||
|
lang === 'none' || !code ? code : Prism.highlight(rawStr, Prism.languages[lang], lang)
|
||||||
const html = rawHtml.replace(new RegExp(TMP_DOT, 'g'), '.').replace(/\n/g, ' ')
|
const html = rawHtml.replace(new RegExp(TMP_DOT, 'g'), '.').replace(/\n/g, ' ')
|
||||||
const result = htmlToReact(html)
|
const result = htmlToReact(html)
|
||||||
const elements = Array.isArray(result) ? result : [result]
|
const elements = Array.isArray(result) ? result : [result]
|
||||||
|
@ -94,12 +103,48 @@ export const TypeAnnotation = ({ lang = 'python', link = true, children }) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function replacePrompt(line, prompt, isFirst = false) {
|
const splitLines = (children) => {
|
||||||
let result = line
|
const listChildrenPerLine = []
|
||||||
const hasPrompt = result.startsWith(`${prompt} `)
|
|
||||||
const showPrompt = hasPrompt || isFirst
|
if (typeof children === 'string') {
|
||||||
if (hasPrompt) result = result.slice(2)
|
listChildrenPerLine.push(...children.split('\n'))
|
||||||
return result && showPrompt ? `<span data-prompt="${prompt}">${result}</span>` : result
|
} else {
|
||||||
|
listChildrenPerLine.push([])
|
||||||
|
let indexLine = 0
|
||||||
|
if (Array.isArray(children)) {
|
||||||
|
children.forEach((child) => {
|
||||||
|
if (typeof child === 'string' && child.includes('\n')) {
|
||||||
|
const listString = child.split('\n')
|
||||||
|
listString.forEach((string, index) => {
|
||||||
|
listChildrenPerLine[indexLine].push(string)
|
||||||
|
|
||||||
|
if (index !== listString.length - 1) {
|
||||||
|
indexLine += 1
|
||||||
|
listChildrenPerLine[indexLine] = []
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
listChildrenPerLine[indexLine].push(child)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
listChildrenPerLine[indexLine].push(children)
|
||||||
|
indexLine += 1
|
||||||
|
listChildrenPerLine[indexLine] = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const listLine = listChildrenPerLine[listChildrenPerLine.length - 1]
|
||||||
|
if (listLine === '' || (listLine.length === 1 && listLine[0] === '')) {
|
||||||
|
listChildrenPerLine.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
return listChildrenPerLine.map((childrenPerLine, index) => (
|
||||||
|
<>
|
||||||
|
{childrenPerLine}
|
||||||
|
{index !== listChildrenPerLine.length - 1 && '\n'}
|
||||||
|
</>
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseArgs(raw) {
|
function parseArgs(raw) {
|
||||||
|
@ -123,82 +168,140 @@ function parseArgs(raw) {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertLine(line, i) {
|
const flattenReact = (children) => {
|
||||||
const cliRegex = /^(\$ )?python -m spacy/
|
if (children === null || children === undefined || children === false) {
|
||||||
if (cliRegex.test(line)) {
|
return []
|
||||||
const text = line.replace(cliRegex, '')
|
|
||||||
const args = parseArgs(text)
|
|
||||||
const cmd = Object.keys(args).map((key, i) => {
|
|
||||||
const value = args[key]
|
|
||||||
return value === null || value === true || i === 0 ? key : `${key} ${value}`
|
|
||||||
})
|
|
||||||
return (
|
|
||||||
<Fragment key={line}>
|
|
||||||
<span data-prompt={i === 0 ? '$' : null} className={classes['cli-arg-subtle']}>
|
|
||||||
python -m
|
|
||||||
</span>{' '}
|
|
||||||
<span>spacy</span>{' '}
|
|
||||||
{cmd.map((item, j) => {
|
|
||||||
const isCmd = j === 0
|
|
||||||
const url = isCmd ? `/api/cli#${item.replace(' ', '-')}` : null
|
|
||||||
const isAbstract = isString(item) && /^\[(.+)\]$/.test(item)
|
|
||||||
const itemClassNames = classNames(classes['cli-arg'], {
|
|
||||||
[classes['cli-arg-highlight']]: isCmd,
|
|
||||||
[classes['cli-arg-emphasis']]: isAbstract,
|
|
||||||
})
|
|
||||||
const text = isAbstract ? item.slice(1, -1) : item
|
|
||||||
return (
|
|
||||||
<Fragment key={j}>
|
|
||||||
{j !== 0 && ' '}
|
|
||||||
<span className={itemClassNames}>
|
|
||||||
<OptionalLink hidden hideIcon to={url}>
|
|
||||||
{text}
|
|
||||||
</OptionalLink>
|
|
||||||
</span>
|
|
||||||
</Fragment>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</Fragment>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
const htmlLine = replacePrompt(highlightCode('bash', line), '$')
|
|
||||||
return htmlToReact(htmlLine)
|
if (typeof children === 'string') {
|
||||||
|
return [children]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (children.props) {
|
||||||
|
return flattenReact(children.props.children)
|
||||||
|
}
|
||||||
|
|
||||||
|
return children.flatMap(flattenReact)
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatCode(html, lang, prompt) {
|
const checkoutForComment = (line) => {
|
||||||
if (lang === 'cli') {
|
const lineParts = line.split(' # ')
|
||||||
const lines = html
|
|
||||||
.trim()
|
if (lineParts.length !== 2) {
|
||||||
.split('\n')
|
return line
|
||||||
.map((line) =>
|
|
||||||
line
|
|
||||||
.split(' | ')
|
|
||||||
.map((l, i) => convertLine(l, i))
|
|
||||||
.map((l, j) => (
|
|
||||||
<Fragment key={j}>
|
|
||||||
{j !== 0 && <span> | </span>}
|
|
||||||
{l}
|
|
||||||
</Fragment>
|
|
||||||
))
|
|
||||||
)
|
|
||||||
return lines.map((line, i) => (
|
|
||||||
<Fragment key={i}>
|
|
||||||
{i !== 0 && <br />}
|
|
||||||
{line}
|
|
||||||
</Fragment>
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
const result = html
|
|
||||||
.split('\n')
|
return (
|
||||||
.map((line, i) => {
|
<>
|
||||||
let newLine = prompt ? replacePrompt(line, prompt, i === 0) : line
|
{lineParts[0]}
|
||||||
if (lang === 'diff' && !line.startsWith('<')) {
|
{` `}
|
||||||
newLine = highlightCode('python', line)
|
<span class="token comment">
|
||||||
}
|
{`# `}
|
||||||
return newLine
|
{lineParts[1]}
|
||||||
})
|
</span>
|
||||||
.join('\n')
|
</>
|
||||||
return htmlToReact(result)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handlePromot = ({ lineFlat, prompt }) => {
|
||||||
|
const lineWithoutPrompt = lineFlat.slice(prompt.length + 1)
|
||||||
|
|
||||||
|
const cliRegex = /^python -m spacy/
|
||||||
|
|
||||||
|
if (!cliRegex.test(lineWithoutPrompt)) {
|
||||||
|
return <span data-prompt={prompt}>{checkoutForComment(lineWithoutPrompt)}</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
const text = lineWithoutPrompt.replace(cliRegex, '')
|
||||||
|
const args = parseArgs(text)
|
||||||
|
const cmd = Object.keys(args).map((key, i) => {
|
||||||
|
const value = args[key]
|
||||||
|
return value === null || value === true || i === 0 ? key : `${key} ${value}`
|
||||||
|
})
|
||||||
|
return (
|
||||||
|
<span data-prompt={prompt}>
|
||||||
|
<span className={classes['cli-arg-subtle']}>python -m</span> <span>spacy</span>{' '}
|
||||||
|
{cmd.map((item, j) => {
|
||||||
|
const isCmd = j === 0
|
||||||
|
const url = isCmd ? `/api/cli#${item.replace(' ', '-')}` : null
|
||||||
|
const isAbstract = isString(item) && /^\[(.+)\]$/.test(item)
|
||||||
|
const itemClassNames = classNames(classes['cli-arg'], {
|
||||||
|
[classes['cli-arg-highlight']]: isCmd,
|
||||||
|
[classes['cli-arg-emphasis']]: isAbstract,
|
||||||
|
})
|
||||||
|
const text = isAbstract ? item.slice(1, -1) : item
|
||||||
|
return (
|
||||||
|
<Fragment key={j}>
|
||||||
|
{j !== 0 && ' '}
|
||||||
|
<span className={itemClassNames}>
|
||||||
|
<OptionalLink hidden hideIcon to={url}>
|
||||||
|
{text}
|
||||||
|
</OptionalLink>
|
||||||
|
</span>
|
||||||
|
</Fragment>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const convertLine = ({ line, prompt, lang }) => {
|
||||||
|
const lineFlat = flattenReact(line).join('')
|
||||||
|
if (lineFlat.startsWith(`${prompt} `)) {
|
||||||
|
return handlePromot({ lineFlat, prompt })
|
||||||
|
}
|
||||||
|
|
||||||
|
return lang === 'none' || !lineFlat ? (
|
||||||
|
lineFlat
|
||||||
|
) : (
|
||||||
|
<span
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: Prism.highlight(lineFlat, Prism.languages[lang], lang),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const addLineHighlight = (children, highlight) => {
|
||||||
|
if (!highlight) {
|
||||||
|
return children
|
||||||
|
}
|
||||||
|
const listHighlight = rangeParser(highlight)
|
||||||
|
|
||||||
|
if (listHighlight.length === 0) {
|
||||||
|
return children
|
||||||
|
}
|
||||||
|
|
||||||
|
return children.map((child, index) => {
|
||||||
|
const isHighlight = listHighlight.includes(index + 1)
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
className={classNames({
|
||||||
|
'gatsby-highlight-code-line': isHighlight,
|
||||||
|
})}
|
||||||
|
key={index}
|
||||||
|
>
|
||||||
|
{child}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CodeHighlighted = ({ children, highlight, lang }) => {
|
||||||
|
const [html, setHtml] = useState()
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
() =>
|
||||||
|
setHtml(
|
||||||
|
addLineHighlight(
|
||||||
|
splitLines(children).map((line) => convertLine({ line, prompt: '$', lang })),
|
||||||
|
highlight
|
||||||
|
)
|
||||||
|
),
|
||||||
|
[children, highlight, lang]
|
||||||
|
)
|
||||||
|
|
||||||
|
return <>{html}</>
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Code extends React.Component {
|
export class Code extends React.Component {
|
||||||
|
@ -207,14 +310,13 @@ export class Code extends React.Component {
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
lang: 'none',
|
lang: 'none',
|
||||||
executable: null,
|
executable: null,
|
||||||
github: false,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
lang: PropTypes.string,
|
lang: PropTypes.string,
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
executable: PropTypes.oneOf(['true', 'false', true, false, null]),
|
executable: PropTypes.oneOf(['true', 'false', true, false, null]),
|
||||||
github: PropTypes.oneOf(['true', 'false', true, false, null]),
|
github: PropTypes.string,
|
||||||
prompt: PropTypes.string,
|
prompt: PropTypes.string,
|
||||||
highlight: PropTypes.string,
|
highlight: PropTypes.string,
|
||||||
className: PropTypes.string,
|
className: PropTypes.string,
|
||||||
|
@ -236,8 +338,7 @@ export class Code extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { lang, title, executable, github, prompt, wrap, highlight, className, children } =
|
const { lang, title, executable, github, wrap, highlight, className, children } = this.props
|
||||||
this.props
|
|
||||||
const codeClassNames = classNames(classes['code'], className, `language-${lang}`, {
|
const codeClassNames = classNames(classes['code'], className, `language-${lang}`, {
|
||||||
[classes['wrap']]: !!highlight || !!wrap || lang === 'cli',
|
[classes['wrap']]: !!highlight || !!wrap || lang === 'cli',
|
||||||
[classes['cli']]: lang === 'cli',
|
[classes['cli']]: lang === 'cli',
|
||||||
|
@ -246,7 +347,7 @@ export class Code extends React.Component {
|
||||||
const { Juniper } = this.state
|
const { Juniper } = this.state
|
||||||
|
|
||||||
if (github) {
|
if (github) {
|
||||||
return <GitHubCode url={children} className={ghClassNames} lang={lang} />
|
return <GitHubCode url={github} className={ghClassNames} lang={lang} />
|
||||||
}
|
}
|
||||||
if (!!executable && Juniper) {
|
if (!!executable && Juniper) {
|
||||||
return (
|
return (
|
||||||
|
@ -256,16 +357,14 @@ export class Code extends React.Component {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const codeText = Array.isArray(children) ? children.join('') : children || ''
|
|
||||||
const highlightRange = highlight ? rangeParser.parse(highlight).filter((n) => n > 0) : []
|
|
||||||
const rawHtml = ['none', 'cli'].includes(lang)
|
|
||||||
? codeText
|
|
||||||
: highlightCode(lang, codeText, highlightRange)
|
|
||||||
const html = formatCode(rawHtml, lang, prompt)
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{title && <h4 className={classes['title']}>{title}</h4>}
|
{title && <h4 className={classes['title']}>{title}</h4>}
|
||||||
<code className={codeClassNames}>{html}</code>
|
<code className={codeClassNames}>
|
||||||
|
<CodeHighlighted highlight={highlight} lang={lang}>
|
||||||
|
{children}
|
||||||
|
</CodeHighlighted>
|
||||||
|
</code>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import React, { useState, useEffect } from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import highlightCode from 'gatsby-remark-prismjs/highlight-code.js'
|
|
||||||
|
|
||||||
import Icon from './icon'
|
import Icon from './icon'
|
||||||
import Link from './link'
|
import Link from './link'
|
||||||
import classes from '../styles/code.module.sass'
|
import classes from '../styles/code.module.sass'
|
||||||
|
import { Code } from './code'
|
||||||
|
|
||||||
const defaultErrorMsg = `Can't fetch code example from GitHub :(
|
const defaultErrorMsg = `Can't fetch code example from GitHub :(
|
||||||
|
|
||||||
|
@ -39,8 +39,6 @@ const GitHubCode = ({ url, lang, errorMsg = defaultErrorMsg, className }) => {
|
||||||
}
|
}
|
||||||
}, [initialized, rawUrl, errorMsg])
|
}, [initialized, rawUrl, errorMsg])
|
||||||
|
|
||||||
const highlighted = lang === 'none' || !code ? code : highlightCode(lang, code)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<header className={classes.header}>
|
<header className={classes.header}>
|
||||||
|
@ -53,7 +51,11 @@ const GitHubCode = ({ url, lang, errorMsg = defaultErrorMsg, className }) => {
|
||||||
</code>
|
</code>
|
||||||
</Link>
|
</Link>
|
||||||
</header>
|
</header>
|
||||||
<code className={codeClassNames} dangerouslySetInnerHTML={{ __html: highlighted }} />
|
{code && (
|
||||||
|
<Code className={codeClassNames} lang={lang}>
|
||||||
|
{code}
|
||||||
|
</Code>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -298,8 +298,8 @@ const Model = ({
|
||||||
{name}
|
{name}
|
||||||
</H2>
|
</H2>
|
||||||
<Aside title="Installation">
|
<Aside title="Installation">
|
||||||
<CodeBlock lang="cli" prompt="$">
|
<CodeBlock lang="bash" prompt="$">
|
||||||
python -m spacy download {name}
|
$ python -m spacy download {name}
|
||||||
</CodeBlock>
|
</CodeBlock>
|
||||||
</Aside>
|
</Aside>
|
||||||
{meta.description && <MarkdownToReact markdown={meta.description} />}
|
{meta.description && <MarkdownToReact markdown={meta.description} />}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user