Skip to content

笔记站的技术使用的是vitepress,使用markdown写笔记,本身对于代码显示来说是有样式(颜色)的

因为我别出心裁的,自己有一个需求,比如说,我想把一大段代码贴到文章里,我可能需要把代码从编辑器里拷贝出来 一大段的贴到md文件里,导致md文件就难看,所以我希望把大段的demo代码提交到github,可以直接引用github的代码,直接显示到文章里,这样写代码和写文字就可以分开了,不用在文章里贴很多的代码了。

具体实现已经ok了,我大概可以将github的代码显示在文章中,具体实现如下 (这里显示的代码就是直接引用的github)

// import Prism from 'prismjs'
// import LoadLanguages from "prismjs/components/index";
// import 'prismjs/themes/prism.css';
import 'prismjs/themes/prism-tomorrow.css'

async function loadPrismLanguage(language: string) {
  switch (language) {
    case 'java':
      return import('prismjs/components/prism-java');
    case 'javadoc':
      return import('prismjs/components/prism-javadoc');
    case 'python':
      return import('prismjs/components/prism-python');
    case 'py':
      return import('prismjs/components/prism-python');
    case 'typescript':
      return import('prismjs/components/prism-typescript');
    case 'ts':
      return import('prismjs/components/prism-typescript');
    case 'css':
      return import('prismjs/components/prism-css');
    case 'c':
      return import('prismjs/components/prism-core');
    case 'cs':
      return import('prismjs/components/prism-csharp');
    case 'cpp':
      return import('prismjs/components/prism-cpp');
    case 'docker':
      return import('prismjs/components/prism-docker');
    case 'git':
      return import('prismjs/components/prism-git');
    case 'go':
      return import('prismjs/components/prism-go');
    case 'gradle':
      return import('prismjs/components/prism-gradle');
    case 'graphql':
      return import('prismjs/components/prism-graphql');
    case 'js':
      return import('prismjs/components/prism-javascript');
    case 'jsdoc':
      return import('prismjs/components/prism-jsdoc');
    case 'json':
      return import('prismjs/components/prism-json');
    case 'webmanifest':
      return import('prismjs/components/prism-json');
    case 'jsonp':
      return import('prismjs/components/prism-jsonp');
    case 'jsx':
      return import('prismjs/components/prism-jsx');
    case 'kt':
      return import('prismjs/components/prism-kotlin');
    case 'kts':
      return import('prismjs/components/prism-kotlin');
    case 'less':
      return import('prismjs/components/prism-less');
    case 'log':
      return import('prismjs/components/prism-log');
    case 'md':
      return import('prismjs/components/prism-markdown');
    case 'mongodb':
      return import('prismjs/components/prism-mongodb');
    case 'perl':
      return import('prismjs/components/prism-perl');
    case 'php':
      return import('prismjs/components/prism-php');
    case 'regex':
      return import('prismjs/components/prism-regex');
    case 'rust':
      return import('prismjs/components/prism-rust');
    case 'ruby':
      return import('prismjs/components/prism-ruby');
    case 'rb':
      return import('prismjs/components/prism-ruby');
    case 'tsx':
      return import('prismjs/components/prism-tsx');
    case 'sass':
      return import('prismjs/components/prism-sass');
    case 'scss':
      return import('prismjs/components/prism-sass');
    case 'scheme':
      return import('prismjs/components/prism-scheme');
    case 'sql':
      return import('prismjs/components/prism-sql');
    case 'swift':
      return import('prismjs/components/prism-swift');
    case 'yaml':
      return import('prismjs/components/prism-yaml');
    case 'yml':
      return import('prismjs/components/prism-yaml');
    default:
      return 'javascript'
  }
}

export default defineComponent({
  props: {
    repo: {
      type: String,
      default: 'o-bricks',
    },
    path: {
      type: String,
      default: '',
    },
    lang: {
      type: String,
      default: '',
    },
  },
  async setup(props) {
    const { repo, path, lang } = props
    const codeRef = ref<HTMLElement | null>(null)
    const owner = 'zack-xy'
    const language = lang || path.split('.').pop()
    const apiUrl = `https://api.github.com/repos/${owner}/${repo}/contents/${path}`

    onMounted(() => {
      if (codeRef.value) {
        import('prismjs').then(Prism => {
          loadPrismLanguage(language || '').then(() => {
            // LoadLanguages(language ? [language] : undefined)
            Prism.highlightElement(codeRef.value!)
          })
        })

      }
    })

    if (!repo || !path) {
      return () => {
        return (
          <div>
            <p>请传入仓库名:repo 和 文件路径:path 参数</p>
          </div>
        )
      }
    }

    try {
      const response = await fetch(apiUrl)
      if (!response.ok) {
        return (
          <div>
            <p>{response.status === 404 ? '未找到代码资源' : '请求github代码出现错误,可能是因为GitHub API受限'}</p>
            <p>请重试,或自行访问:<a target="_blank" rel="noopener noreferrer" href={`https://github.com/${owner}/${repo}/blob/main/${path}`}>github代码地址</a></p>
          </div>
        )
      }
      const data = await response.json()
      const content = atob(data.content)
      const uint8Array = new Uint8Array(content.length)
      for (let i = 0; i < content.length; i++)
        uint8Array[i] = content.charCodeAt(i)
      // 使用 TextDecoder 指定 utf-8 编码进行解码
      const decoder = new TextDecoder('utf-8')
      const decodedString = decoder.decode(uint8Array)
      return () => {
        return (
          <pre>
            <code ref={codeRef} class={`language-${language}`}>
              {decodedString}
            </code>
          </pre>
        )
      }
    }
    catch (error) {
      return (
        <div>
          <p>请求github代码出现错误:{error}</p>
          <p>请重试,或自行访问<a target="_blank" rel="noopener noreferrer" href={`https://github.com/${owner}/${repo}/blob/main/${path}`}>github代码地址</a></p>
        </div>
      )
    }
  },
})

代码的样式(颜色)我是使用的是prismjs

最近我发现,写的java代码,没有代码样式。

检查了一下包的用法,发现应该是相关的js没有引入

但是这个包是CJS的,我是ESM项目,官方的增加语言支持的API也就是loadLanguages我用不了,这个API内部用的require.resolve会报错

需要修改成import动态导入的形式

import('prismjs').then(Prism => {
  .....
})

类型报错,需要增加一个prismjs.d.ts文件

// types/prismjs.d.ts
declare module 'prismjs/components/*' {
  import { Grammar } from 'prismjs';
  const grammar: Grammar;
  export default grammar;
}

还有一点问题:

  1. 因为是import动态导入,没有办法按不同语言自动导入,需要提前列出来,就是上面代码loadPrismLanguage那一大坨,看起来很丑。
  2. 如上文试了一下tsx,发现不ok,好像报错了,简单看了一眼应该是包内部报的错,可能需要改包,先不管了