Compare commits

4 Commits

Author SHA1 Message Date
Redon
94e23bb916 chore: version 2.8.2 (#159)
* fix: 修复普通文本代码渲染和深色模式下的问题[#139][#154]

* chore: version 2.8.2
2023-02-28 10:00:53 +08:00
Redon
21fb4f817c fix: HTML 渲染异常 (#152)
* fix: 修复 `API` 版本 HTML 会被渲染的问题[#146]

* chore: version 2.8.1
2023-02-27 19:25:15 +08:00
二丫讲梵
2c509c329f feat: 调整镜像构建的tag,让最新代码指向latest,让每次版本指向日期 (#144)
* feat: 调整镜像构建的tag,让最新代码指向latest,让每次版本指向日期

* feat: 触发时机为main分支push或者relases的create,镜像的tag为分支名或tag名

* fix: 修复变量引用方式

* fix: 修复变量引用方式

* fix: 使用github.ref_name 取触发action的来源
2023-02-27 19:24:46 +08:00
ChenZhaoYu
4769c31d09 fix: white space 2023-02-27 13:01:42 +08:00
14 changed files with 310 additions and 29 deletions

View File

@@ -3,6 +3,8 @@ name: build_docker
on:
push:
branches: [main]
release:
types: [created] # 表示在创建新的 Release 时触发
jobs:
build_docker:
@@ -11,11 +13,11 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
images: chenzhaoyu94/chatgpt-web
- run: |
echo "本次构建的版本为:${GITHUB_REF_NAME} (但是这个变量目前上下文中无法获取到)"
echo 本次构建的版本为:${{ github.ref_name }}
env
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
@@ -32,6 +34,8 @@ jobs:
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64,linux/arm64
tags: |
${{ secrets.DOCKERHUB_USERNAME }}/chatgpt-web:${{ github.ref_name }}
${{ secrets.DOCKERHUB_USERNAME }}/chatgpt-web:latest

View File

@@ -29,6 +29,7 @@
"dockerhub",
"esno",
"GPTAPI",
"hljs",
"iconify",
"logprobs",
"nodata",

View File

@@ -1,3 +1,18 @@
## v2.8.2
`2023-02-28`
### Enhancement
- 代码主题调整为 `One Dark - light|dark` 适配深色模式
### BugFix
- 修复普通文本代码渲染和深色模式下的问题[#139][#154]
## v2.8.1
`2023-02-27`
### BugFix
- 修复 `API` 版本不是 `Markdown` 时,普通 `HTML` 代码会被渲染的问题 [#146]
## v2.8.0
`2023-02-27`

View File

@@ -174,7 +174,7 @@ version: '3'
services:
app:
image: chenzhaoyu94/chatgpt-web:main
image: chenzhaoyu94/chatgpt-web # 总是使用latest,更新时重新pull该tag镜像即可
ports:
- 3002:3002
environment:

View File

@@ -1,6 +1,6 @@
{
"name": "chatgpt-web",
"version": "2.8.0",
"version": "2.8.2",
"private": false,
"description": "ChatGPT Web",
"author": "ChenZhaoYu <chenzhaoyu1994@gmail.com>",

View File

@@ -0,0 +1,23 @@
import type { App, Directive } from 'vue'
import hljs from 'highlight.js'
import { includeCode } from '@/utils/format'
hljs.configure({ ignoreUnescapedHTML: true })
function highlightCode(el: HTMLElement) {
if (includeCode(el.textContent))
hljs.highlightBlock(el)
}
export default function setupHighlightDirective(app: App) {
const highLightDirective: Directive<HTMLElement> = {
mounted(el: HTMLElement) {
highlightCode(el)
},
updated(el: HTMLElement) {
highlightCode(el)
},
}
app.directive('highlight', highLightDirective)
}

View File

@@ -1 +1,6 @@
export function setupDirectives() {}
import type { App } from 'vue'
import setupHighlightDirective from './highlight'
export function setupDirectives(app: App) {
setupHighlightDirective(app)
}

View File

@@ -1,5 +1,6 @@
import { createApp } from 'vue'
import App from './App.vue'
import { setupDirectives } from './directives'
import { setupAssets } from '@/plugins'
import { setupStore } from '@/store'
import { setupRouter } from '@/router'
@@ -10,6 +11,8 @@ async function bootstrap() {
setupStore(app)
setupDirectives(app)
await setupRouter(app)
app.mount('#app')

View File

@@ -1,5 +1,5 @@
import 'highlight.js/styles/xcode.css'
import '@/styles/lib/tailwind.css'
import '@/styles/lib/highlight.less'
import '@/styles/lib/github-markdown.less'
import '@/styles/global.less'

View File

@@ -0,0 +1,203 @@
html.dark {
pre code.hljs {
display: block;
overflow-x: auto;
padding: 1em
}
code.hljs {
padding: 3px 5px
}
.hljs {
color: #abb2bf;
background: #282c34
}
.hljs-keyword,
.hljs-operator,
.hljs-pattern-match {
color: #f92672
}
.hljs-function,
.hljs-pattern-match .hljs-constructor {
color: #61aeee
}
.hljs-function .hljs-params {
color: #a6e22e
}
.hljs-function .hljs-params .hljs-typing {
color: #fd971f
}
.hljs-module-access .hljs-module {
color: #7e57c2
}
.hljs-constructor {
color: #e2b93d
}
.hljs-constructor .hljs-string {
color: #9ccc65
}
.hljs-comment,
.hljs-quote {
color: #b18eb1;
font-style: italic
}
.hljs-doctag,
.hljs-formula {
color: #c678dd
}
.hljs-deletion,
.hljs-name,
.hljs-section,
.hljs-selector-tag,
.hljs-subst {
color: #e06c75
}
.hljs-literal {
color: #56b6c2
}
.hljs-addition,
.hljs-attribute,
.hljs-meta .hljs-string,
.hljs-regexp,
.hljs-string {
color: #98c379
}
.hljs-built_in,
.hljs-class .hljs-title,
.hljs-title.class_ {
color: #e6c07b
}
.hljs-attr,
.hljs-number,
.hljs-selector-attr,
.hljs-selector-class,
.hljs-selector-pseudo,
.hljs-template-variable,
.hljs-type,
.hljs-variable {
color: #d19a66
}
.hljs-bullet,
.hljs-link,
.hljs-meta,
.hljs-selector-id,
.hljs-symbol,
.hljs-title {
color: #61aeee
}
.hljs-emphasis {
font-style: italic
}
.hljs-strong {
font-weight: 700
}
.hljs-link {
text-decoration: underline
}
}
html {
pre code.hljs {
display: block;
overflow-x: auto;
padding: 1em
}
code.hljs {
padding: 3px 5px
}
.hljs {
color: #383a42;
background: #fafafa
}
.hljs-comment,
.hljs-quote {
color: #a0a1a7;
font-style: italic
}
.hljs-doctag,
.hljs-formula,
.hljs-keyword {
color: #a626a4
}
.hljs-deletion,
.hljs-name,
.hljs-section,
.hljs-selector-tag,
.hljs-subst {
color: #e45649
}
.hljs-literal {
color: #0184bb
}
.hljs-addition,
.hljs-attribute,
.hljs-meta .hljs-string,
.hljs-regexp,
.hljs-string {
color: #50a14f
}
.hljs-attr,
.hljs-number,
.hljs-selector-attr,
.hljs-selector-class,
.hljs-selector-pseudo,
.hljs-template-variable,
.hljs-type,
.hljs-variable {
color: #986801
}
.hljs-bullet,
.hljs-link,
.hljs-meta,
.hljs-selector-id,
.hljs-symbol,
.hljs-title {
color: #4078f2
}
.hljs-built_in,
.hljs-class .hljs-title,
.hljs-title.class_ {
color: #c18401
}
.hljs-emphasis {
font-style: italic
}
.hljs-strong {
font-weight: 700
}
.hljs-link {
text-decoration: underline
}
}

15
src/utils/format/index.ts Normal file
View File

@@ -0,0 +1,15 @@
// 转义 HTML 字符
export function encodeHTML(source: string) {
return source
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;')
}
// 判断是否为代码块
export function includeCode(text: string | null | undefined) {
const regexp = /^(?:\s{4}|\t).+/gm
return !!(text?.includes(' = ') || text?.match(regexp))
}

View File

@@ -1,6 +0,0 @@
function includeCode(text: string | null | undefined) {
const regexp = /^(?:\s{4}|\t).+/gm
return !!(text?.includes(' = ') || text?.match(regexp))
}
export default includeCode

View File

@@ -3,6 +3,7 @@ import { computed } from 'vue'
import { marked } from 'marked'
import hljs from 'highlight.js'
import { useBasicLayout } from '@/hooks/useBasicLayout'
import { encodeHTML } from '@/utils/format'
interface Props {
inversion?: boolean
@@ -15,8 +16,21 @@ const props = defineProps<Props>()
const { isMobile } = useBasicLayout()
const renderer = new marked.Renderer()
renderer.html = (html) => {
return `<p>${encodeHTML(html)}</p>`
}
renderer.code = (code, language) => {
const validLang = !!(language && hljs.getLanguage(language))
if (validLang)
return `<pre><code class="hljs ${language}">${hljs.highlight(language, code).value}</code></pre>`
return `<pre style="background: none">${hljs.highlightAuto(code).value}</pre>`
}
marked.setOptions({
renderer: new marked.Renderer(),
renderer,
highlight(code) {
return hljs.highlightAuto(code).value
},
@@ -35,9 +49,10 @@ const wrapClass = computed(() => {
})
const text = computed(() => {
if (props.text && !props.inversion)
return marked(props.text)
return props.text
const value = props.text ?? ''
if (!props.inversion)
return marked(value)
return value
})
</script>
@@ -48,7 +63,7 @@ const text = computed(() => {
</template>
<template v-else>
<div class="leading-relaxed break-all">
<pre v-if="!inversion" class="markdown-body" v-html="text" />
<div v-if="!inversion" class="markdown-body" v-html="text" />
<div v-else class="whitespace-pre-wrap" v-text="text" />
</div>
</template>

View File

@@ -2,7 +2,7 @@
background-color: transparent;
font-size: 14px;
p{
p {
white-space: pre-wrap;
}
@@ -23,13 +23,16 @@
pre {
background-color: #fff;
}
}
.dark{
.markdown-body{
.highlight pre,
pre {
background-color: #18181c;
}
code.hljs{
padding: 0;
}
}
html.dark {
.highlight pre,
pre {
background-color: #282c34;
}
}