Can now view markdown both rendered and raw
This commit is contained in:
parent
91bb7cb7e6
commit
036fb0f0b1
9 changed files with 121 additions and 20 deletions
|
@ -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) {
|
||||||
|
|
48
src/app/[...file]/components/tab_group.css.ts
Normal file
48
src/app/[...file]/components/tab_group.css.ts
Normal 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,
|
||||||
|
});
|
||||||
|
|
19
src/app/[...file]/components/tab_group.tsx
Normal file
19
src/app/[...file]/components/tab_group.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
|
@ -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%',
|
||||||
});
|
});
|
||||||
|
|
|
@ -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>)}
|
||||||
|
</>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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',
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue