mirror of
https://github.com/wavetermdev/backup.git
synced 2026-08-05 13:57:07 -07:00
markdown preview
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
.markdown {
|
||||
color: var(--main-color);
|
||||
font-family: var(--markdown-font);
|
||||
font-size: 14px;
|
||||
overflow-wrap: break-word;
|
||||
|
||||
&.bottom-margin {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: var(--main-color);
|
||||
margin-top: 16px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
strong {
|
||||
color: var(--main-color);
|
||||
}
|
||||
|
||||
a {
|
||||
color: #32afff;
|
||||
}
|
||||
|
||||
table {
|
||||
tr th {
|
||||
color: var(--main-color);
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: disc;
|
||||
list-style-position: outside;
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
ol {
|
||||
list-style-position: outside;
|
||||
margin-left: 19px;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 4px 10px 4px 10px;
|
||||
border-radius: 3px;
|
||||
background-color: var(--panel-bg-color);
|
||||
padding: 2px 4px 2px 6px;
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: var(--panel-bg-color);
|
||||
margin: 4px 10px 4px 10px;
|
||||
padding: 0.7em;
|
||||
border-radius: 4px;
|
||||
|
||||
code {
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
line-height: normal;
|
||||
}
|
||||
}
|
||||
|
||||
code {
|
||||
font: var(--fixed-font);
|
||||
color: var(--main-color);
|
||||
border-radius: 4px;
|
||||
background-color: var(--panel-bg-color);
|
||||
padding: 0.15em 0.5em;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: semibold;
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.title.is-1 {
|
||||
border-bottom: 1px solid #777;
|
||||
padding-bottom: 6px;
|
||||
font-size: 2em;
|
||||
}
|
||||
.title.is-2 {
|
||||
border-bottom: 1px solid #777;
|
||||
padding-bottom: 6px;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
.title.is-3 {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
.title.is-4 {
|
||||
font-size: 1em;
|
||||
}
|
||||
.title.is-5 {
|
||||
font-size: 0.875em;
|
||||
}
|
||||
.title.is-6 {
|
||||
font-size: 0.85em;
|
||||
}
|
||||
}
|
||||
|
||||
.markdown > *:first-child {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import * as React from "react";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import { clsx } from "clsx";
|
||||
|
||||
import "./markdown.less";
|
||||
|
||||
function LinkRenderer(props: any): any {
|
||||
let newUrl = "https://extern?" + encodeURIComponent(props.href);
|
||||
return (
|
||||
<a href={newUrl} target="_blank" rel={"noopener"}>
|
||||
{props.children}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
function HeaderRenderer(props: any, hnum: number): any {
|
||||
return <div className={clsx("title", "is-" + hnum)}>{props.children}</div>;
|
||||
}
|
||||
|
||||
function Markdown(props: { text: string; style?: any; extraClassName?: string; codeSelect?: boolean }) {
|
||||
let text = props.text;
|
||||
let markdownComponents = {
|
||||
a: LinkRenderer,
|
||||
h1: (props) => HeaderRenderer(props, 1),
|
||||
h2: (props) => HeaderRenderer(props, 2),
|
||||
h3: (props) => HeaderRenderer(props, 3),
|
||||
h4: (props) => HeaderRenderer(props, 4),
|
||||
h5: (props) => HeaderRenderer(props, 5),
|
||||
h6: (props) => HeaderRenderer(props, 6),
|
||||
};
|
||||
return (
|
||||
<div className={clsx("markdown", props.extraClassName)} style={props.style}>
|
||||
<ReactMarkdown remarkPlugins={[remarkGfm]} components={markdownComponents}>
|
||||
{text}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export { Markdown };
|
||||
@@ -24,7 +24,7 @@ const blockAtomFamily = atomFamily<string, jotai.Atom<BlockData>>((blockId: stri
|
||||
return jotai.atom({ blockid: blockId1, view: "term" });
|
||||
}
|
||||
if (blockId === blockId2) {
|
||||
return jotai.atom({ blockid: blockId2, view: "preview" });
|
||||
return jotai.atom({ blockid: blockId2, view: "preview", meta: { mimetype: "text/markdown" } });
|
||||
}
|
||||
if (blockId === blockId3) {
|
||||
return jotai.atom({ blockid: blockId3, view: "term" });
|
||||
|
||||
@@ -22,10 +22,4 @@
|
||||
border-radius: 4px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.block1 {
|
||||
}
|
||||
|
||||
.block2 {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,37 @@
|
||||
|
||||
import * as React from "react";
|
||||
import * as jotai from "jotai";
|
||||
import { atoms } from "@/store/global";
|
||||
import { Markdown } from "@/element/markdown";
|
||||
|
||||
import "./view.less";
|
||||
|
||||
const markdownText = `
|
||||
# Markdown Preview
|
||||
|
||||
* list item 1
|
||||
* list item 2
|
||||
* item 3
|
||||
|
||||
\`\`\`
|
||||
let foo = "bar";
|
||||
console.log(foo);
|
||||
\`\`\`
|
||||
`;
|
||||
|
||||
const MarkdownPreview = ({ blockData }: { blockData: BlockData }) => {
|
||||
return (
|
||||
<div className="view-preview view-preview-markdown">
|
||||
<Markdown text={markdownText} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const PreviewView = ({ blockId }: { blockId: string }) => {
|
||||
const blockData: BlockData = jotai.useAtomValue(atoms.blockAtomFamily(blockId));
|
||||
if (blockData.meta?.mimetype === "text/markdown") {
|
||||
return <MarkdownPreview blockData={blockData} />;
|
||||
}
|
||||
return (
|
||||
<div className="view-preview">
|
||||
<div>Preview</div>
|
||||
|
||||
@@ -18,4 +18,9 @@
|
||||
overflow: hidden;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
&.view-preview-markdown {
|
||||
align-items: start;
|
||||
justify-content: start;
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+1
@@ -11,6 +11,7 @@ declare global {
|
||||
type BlockData = {
|
||||
blockid: string;
|
||||
view: string;
|
||||
meta?: Record<string, any>;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"log"
|
||||
|
||||
"github.com/wavetermdev/thenextwave/pkg/blockstore"
|
||||
"github.com/wavetermdev/thenextwave/pkg/service/fileservice"
|
||||
"github.com/wavetermdev/thenextwave/pkg/wavebase"
|
||||
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
@@ -45,6 +46,7 @@ func main() {
|
||||
Description: "The Next Wave Terminal",
|
||||
Bind: []any{
|
||||
&GreetService{},
|
||||
&fileservice.FileService{},
|
||||
},
|
||||
Icon: appIcon,
|
||||
Assets: application.AssetOptions{
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
"jotai": "^2.8.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-markdown": "^9.0.1",
|
||||
"remark-gfm": "^4.0.0",
|
||||
"rxjs": "^7.8.1",
|
||||
"uuid": "^9.0.1"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package fileservice
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/wavetermdev/thenextwave/pkg/wavebase"
|
||||
)
|
||||
|
||||
type FileService struct{}
|
||||
|
||||
func (fs *FileService) ReadFile(path string) ([]byte, error) {
|
||||
path = wavebase.ExpandHomeDir(path)
|
||||
return os.ReadFile(path)
|
||||
}
|
||||
@@ -12,6 +12,8 @@
|
||||
--app-accent-color: rgb(88, 193, 66);
|
||||
--panel-bg-color: rgba(31, 33, 31, 1);
|
||||
--highlight-bg-color: rgba(255, 255, 255, 0.2);
|
||||
--markdown-font: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif,
|
||||
"Apple Color Emoji", "Segoe UI Emoji";
|
||||
}
|
||||
|
||||
body {
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"@/app/*": ["frontend/app/*"],
|
||||
"@/util/*": ["frontend/util/*"],
|
||||
"@/store/*": ["frontend/app/store/*"],
|
||||
"@/element/*": ["frontend/app/element/*"],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user