Can now view markdown both rendered and raw

This commit is contained in:
Gnarwhal 2024-09-23 21:21:45 +00:00
parent 91bb7cb7e6
commit 036fb0f0b1
Signed by: Gnarwhal
GPG key ID: 0989A73D8C421174
9 changed files with 121 additions and 20 deletions

View file

@ -57,7 +57,7 @@ export default function Content({ src }: { src: string}) {
}; };
} }
}, { }, {
content_type: /application\/octet-stream/, content_type: /(text\/markdown|application\/octet-stream)/,
path: /.*\.md/i, path: /.*\.md/i,
emit: () => { emit: () => {
return { return {
@ -70,7 +70,7 @@ export default function Content({ src }: { src: string}) {
}; };
} }
}, { }, {
content_type: /(text\/\w+)|(application\/octet-stream)/, content_type: /(text\/\w+|application\/octet-stream)/,
emit: () => { emit: () => {
return { return {
process: (response: Response) => { process: (response: Response) => {
@ -86,7 +86,7 @@ export default function Content({ src }: { src: string}) {
useEffect(() => { useEffect(() => {
if (content == undefined) { if (content == undefined) {
const result = fetch(src) const result = fetch(src, { cache: "no-cache" })
.then(response => { .then(response => {
if (response.status < 400) { if (response.status < 400) {
for (const type of recognized_types) { for (const type of recognized_types) {

View file

@ -0,0 +1,48 @@
import { style } from '@vanilla-extract/css';
import * as colors from '../../colors.css';
export const tab_group = style({
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: '100%',
height: '2em',
borderBottom: `1px solid ${colors.background2}`,
'@media': {
'screen and (max-width: 768px)': {
height: '1.75em',
}
}
});
export const tab = style({
border: 'none',
outline: 'none',
backgroundColor: 'inherit',
color: 'inherit',
width: '10em',
fontSize: '1em',
height: '100%',
flexGrow: 0,
transition: 'color 0.35s, background-color 0.35s',
':hover': {
backgroundColor: colors.background2,
},
'@media': {
'screen and (max-width: 768px)': {
fontSize: '0.9em',
}
},
});
export const active = style({
backgroundColor: colors.background2,
});
export const separator = style({
width: '1px',
height: '100%',
backgroundColor: colors.background2,
});

View file

@ -0,0 +1,19 @@
'use client'
import React from 'react';
import { useState } from 'react';
import * as style from './tab_group.css';
export default function TabGroup({ tabs, initial, tab_callback }: { tabs: string[], initial: number, tab_callback: (active: number) => void }) {
const [active, set_active] = useState(initial);
return (
<div className={style.tab_group}>
<div className={style.separator}></div>
{tabs.map((tab, index) => <React.Fragment key={index}>
<button onClick={() => { set_active(index); tab_callback(index); }} className={`${style.tab} ${index == active ? style.active : ''}`}>{tab}</button>
<div className={style.separator}></div>
</React.Fragment>)}
</div>
);
}

View file

@ -1,5 +1,6 @@
import { style } from '@vanilla-extract/css' import { style } from '@vanilla-extract/css'
export const image = style({ export const image = style({
marginTop: '1em',
maxWidth: '100%', maxWidth: '100%',
}); });

View file

@ -1,24 +1,54 @@
'use client'
import { useRef } from 'react';
import Markdown from 'react-markdown'; import Markdown from 'react-markdown';
import * as style from './markdown.css'; import * as style from './markdown.css';
import TabGroup from '../tab_group';
import Copy from '../copy'; import Copy from '../copy';
import Text from './text'; import Text from './text';
import { map_to_type } from './text'; import { map_to_type } from './text';
const initial = 0;
export default function MarkdownContent({ text }: { text: string }) { export default function MarkdownContent({ text }: { text: string }) {
return ( /*
<Markdown * Originally used 'useState', but switching back to the 'Rendered'
components={{ * tab from 'Raw' was expensive and caused a hiccup
'code': (props) => { *
const split = props.className?.split('-') ?? ['none']; * Now, keep them both loaded in the DOM and use display to switch
return ( * which is being rendered. It's less "Reactive" or whatever, but
<div className={style.code_bounds}> * it is simply faster ¯\_()_/¯
<Copy className={style.copy} text={props.children as string}></Copy> */
<Text language={split.length == 0 ? 'none' : map_to_type(split[split.length - 1])} text={props.children as string} line_numbers={false} /> const refs = [
</div> useRef<HTMLDivElement | null>(null),
); useRef<HTMLDivElement | null>(null),
} ]
}}
>{text}</Markdown> function tab_callback(active: number) {
); for (const [index, ref] of refs.entries()) {
ref.current!.style.display = index == active ? 'block' : 'none';
}
}
return <>
<TabGroup tabs={[ 'Rendered', 'Raw' ]} initial={initial} tab_callback={tab_callback} />
{[
<Markdown
key={0}
components={{
'code': (props) => {
const split = props.className?.split('-') ?? ['none'];
return (
<div className={style.code_bounds}>
<Copy className={style.copy} text={props.children as string}></Copy>
<Text language={split.length == 0 ? 'none' : map_to_type(split[split.length - 1])} text={props.children as string} line_numbers={false} />
</div>
);
}
}}
>{text}</Markdown>,
<Text key={1} language={"markdown"} text={text} line_numbers={true} />
].map((tab, index) => <div key={index} ref={refs[index]} style={{ display: index == initial ? 'block' : 'none' }}>{tab}</div>)}
</>;
} }

View file

@ -2,6 +2,7 @@ import { style } from '@vanilla-extract/css'
export const content = style({ export const content = style({
margin: 0, margin: 0,
marginTop: '0.9em',
fontFamily: 'monospace', fontFamily: 'monospace',
fontSize: '1.1em', fontSize: '1.1em',
lineHeight: '1.4em', lineHeight: '1.4em',

View file

@ -3,6 +3,7 @@ import { style } from '@vanilla-extract/css'
import * as colors from '../../../colors.css' import * as colors from '../../../colors.css'
export const group = style({ export const group = style({
marginTop: '0.5em',
display: 'flex', display: 'flex',
fontFamily: 'monospace', fontFamily: 'monospace',
fontSize: '1em', fontSize: '1em',

View file

@ -36,6 +36,8 @@ const type_map = {
py: 'python', py: 'python',
python: 'python', python: 'python',
json: 'json', json: 'json',
md: 'markdown',
markdown: 'markdown',
none: 'none', none: 'none',
} }

View file

@ -18,7 +18,6 @@ export const center = style({
}); });
export const title_group = style({ export const title_group = style({
marginBottom: '0.5em',
width: '100%', width: '100%',
height: '3.5em', height: '3.5em',
display: 'flex', display: 'flex',
@ -101,7 +100,7 @@ export const download_tty_group = style({
'screen and (min-width: 768px)': { 'screen and (min-width: 768px)': {
display: 'block', display: 'block',
margin: 0, margin: 0,
marginBottom: '1em', marginTop: '0.5em',
borderBottom: `1px solid ${colors.background2}`, borderBottom: `1px solid ${colors.background2}`,
paddingBottom: '0.5em', paddingBottom: '0.5em',
}, },