From f5c21698a09d9214f57ce6dab2595f3d61e1ff11 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Thu, 7 Jan 2021 13:22:21 +0300 Subject: feat!: use react-markdown --- src/lib/Markdown/CodeBlock.tsx | 13 ++++-- src/lib/Markdown/Content.tsx | 90 ----------------------------------- src/lib/Markdown/Heading.tsx | 33 +++++++++++++ src/lib/Markdown/Image.tsx | 12 +++++ src/lib/Markdown/InlineCode.tsx | 18 +++++++ src/lib/Markdown/Markdown.tsx | 27 +++++++++-- src/lib/Markdown/Section.tsx | 61 ------------------------ src/lib/Markdown/SyntacticSpan.tsx | 96 -------------------------------------- src/lib/Markdown/Text.tsx | 13 ------ 9 files changed, 94 insertions(+), 269 deletions(-) delete mode 100644 src/lib/Markdown/Content.tsx create mode 100644 src/lib/Markdown/Heading.tsx create mode 100644 src/lib/Markdown/Image.tsx create mode 100644 src/lib/Markdown/InlineCode.tsx delete mode 100644 src/lib/Markdown/Section.tsx delete mode 100644 src/lib/Markdown/SyntacticSpan.tsx delete mode 100644 src/lib/Markdown/Text.tsx (limited to 'src') diff --git a/src/lib/Markdown/CodeBlock.tsx b/src/lib/Markdown/CodeBlock.tsx index 394458e..7431881 100644 --- a/src/lib/Markdown/CodeBlock.tsx +++ b/src/lib/Markdown/CodeBlock.tsx @@ -1,8 +1,9 @@ import React from 'react'; -import { Paper } from '@material-ui/core'; +import { Paper, makeStyles } from '@material-ui/core'; -import { makeStyles } from '@material-ui/core/styles'; -import { ParserPropTypes } from './types'; +interface PropTypes { + value: string; +} const useStyles = makeStyles(theme => ({ root: { @@ -14,11 +15,13 @@ const useStyles = makeStyles(theme => ({ }, })); -const CodeBlock: React.FC = ({ rawLines }) => { +const CodeBlock: React.FC = ({ value }) => { const classes = useStyles(); return ( - {rawLines.map(line =>
{line}
)} +
+        {value}
+      
); }; diff --git a/src/lib/Markdown/Content.tsx b/src/lib/Markdown/Content.tsx deleted file mode 100644 index 88409fa..0000000 --- a/src/lib/Markdown/Content.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import React from 'react'; - -import CodeBlock from './CodeBlock'; -import Text from './Text'; -import { ParserPropTypes } from './types'; - - -const denotesCodeBlock = (line: string): boolean => { - return line.match(/^\s*```.*$/) !== null; -}; - -const denotesDottedList = (line: string): boolean => { - return line.match(/^ ?[-*] .*$/) !== null; -}; - -const denotesOpenHtml = (line: string): string => { - const regex = /<([^/\s]*)[^<]*[^/]>/g; - const match = regex.exec(line); - return match ? match[1] : ''; -}; - -const denotesClosingHtml = (line: string, tag: string): boolean => { - const regex = new RegExp(``); - return line.match(regex) !== null; -}; - -const denotesSelfClosingHtml = (line: string): string[] | null => { - const regex = /(<[^/\s]*[^<]*\/>)/g; - return line.match(regex); -}; - -const declaresNoLineBreak = (line: string): boolean => { - return line.match(/\\\|$/) !== null; -}; - -const Content: React.FC = ({ rawLines }) => { - if (!rawLines.length) return null; - - const line = rawLines.splice(0, 1)[0]; - - let buffer; - if (denotesCodeBlock(line)) { - const closeIndex = rawLines.findIndex(rawLine => denotesCodeBlock(rawLine)); - const codeBlockLines = rawLines.splice(0, closeIndex + 1).slice(0, closeIndex); - buffer = ; - } else if (denotesDottedList(line)) { - const closeIndex = rawLines.findIndex(rawLine => !denotesDottedList(rawLine)); - const dottedListLines = rawLines.splice(0, closeIndex).slice(0, closeIndex); - dottedListLines.unshift(line); - buffer =
    {dottedListLines.map(li =>
  • )}
; - } else if ((buffer = denotesOpenHtml(line))) { - const tag = buffer; - const closeIndex = denotesClosingHtml(line, tag) ? -1 : rawLines.findIndex( - rawLine => denotesClosingHtml(rawLine, tag), - ); - const htmlLines = rawLines.splice(0, closeIndex + 1); - htmlLines.unshift(line); - buffer =
; - } else if ((buffer = denotesSelfClosingHtml(line)) !== null) { - const match = buffer[0]; - const [before, after] = line.split(match); - buffer = ( - <> - -
- - - ); - } else if (declaresNoLineBreak(line)) { - const closeIndex = rawLines.findIndex(rawLine => !declaresNoLineBreak(rawLine)); - const lineBreakLines = rawLines.splice(0, closeIndex).map(rawLine => rawLine.slice(0, -2)); - lineBreakLines.unshift(line.slice(0, -2)); - lineBreakLines.push(rawLines.splice(0, 1)[0]); - buffer =

{lineBreakLines.map(lineBreakLine => )}

; - } else if (denotesClosingHtml(line, '')) { - buffer = null; - } else { - buffer =

; - } - - return ( - <> - { buffer } - - - ); -}; - -export default Content; - diff --git a/src/lib/Markdown/Heading.tsx b/src/lib/Markdown/Heading.tsx new file mode 100644 index 0000000..cc0b709 --- /dev/null +++ b/src/lib/Markdown/Heading.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import { Typography, Divider, makeStyles } from '@material-ui/core'; + +interface PropTypes { + level: number; +} + +type Variant = 'h3' | 'h4' | 'h5' | 'h6'; + +const useStyles = makeStyles(theme => ({ + root: { + padding: theme.spacing(2, 0, 1, 0), + }, +})); + +const Heading: React.FC = ({ children, level }) => { + const classes = useStyles(); + + let adjustedLevel = level + 2; // Make everything smaller + if (adjustedLevel > 6) adjustedLevel = 6; + + const variant: Variant = `h${adjustedLevel}` as Variant; + + return ( +
+ {children} + +
+ ); +}; + +export default Heading; + diff --git a/src/lib/Markdown/Image.tsx b/src/lib/Markdown/Image.tsx new file mode 100644 index 0000000..472d6f0 --- /dev/null +++ b/src/lib/Markdown/Image.tsx @@ -0,0 +1,12 @@ +import React from 'react'; + +interface PropTypes { + src: string; + alt: string; +} + +const Image: React.FC = ({ src, alt }) => { + return {alt}; +}; + +export default Image; diff --git a/src/lib/Markdown/InlineCode.tsx b/src/lib/Markdown/InlineCode.tsx new file mode 100644 index 0000000..c51f924 --- /dev/null +++ b/src/lib/Markdown/InlineCode.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { makeStyles } from '@material-ui/core'; + +const useStyles = makeStyles(theme => ({ + root: { + background: theme.palette.background.default, + borderRadius: theme.spacing(0.5), + padding: theme.spacing(0.5), + fontFamily: 'Monospace', + }, +})); + +const InlineCode: React.FC = ({ children }) => { + const classes = useStyles(); + return {children}; +}; + +export default InlineCode; diff --git a/src/lib/Markdown/Markdown.tsx b/src/lib/Markdown/Markdown.tsx index cfcf117..01923f9 100644 --- a/src/lib/Markdown/Markdown.tsx +++ b/src/lib/Markdown/Markdown.tsx @@ -1,7 +1,12 @@ import React, { useState, useEffect } from 'react'; import axios from 'axios'; +import ReactMarkdown from 'react-markdown'; +import { Link, Typography } from '@material-ui/core'; -import Section from './Section'; +import CodeBlock from './CodeBlock'; +import InlineCode from './InlineCode'; +import Heading from './Heading'; +import Image from './Image'; interface PropTypes { data?: string; @@ -12,10 +17,18 @@ const resolveUrls = (line: string, baseUrl: string): string => line.replace( /src="(?!http)(.*)"[\s>]/, (match, url) => `src="${baseUrl}/${url}?sanitize=true"`, ).replace( - /\[(.*\]?.*)\]\((?!http)(.+?)\)/, + /\[(.*\]?.*)\]\((?!http)(.+?)\)/g, (match, text, url) => `[${text}](${baseUrl}/${url})`, ); +const renderers = { + heading: Heading, + inlineCode: InlineCode, + code: CodeBlock, + link: Link, + image: Image, +}; + const Markdown: React.FC = ({ data, url }) => { const [markdown, setMarkdown] = useState(data || ''); @@ -26,8 +39,14 @@ const Markdown: React.FC = ({ data, url }) => { }, [data, url]); const baseUrl = url?.slice(0, url.lastIndexOf('/')) || ''; - const lines = markdown.split(/\r?\n/).map(line => resolveUrls(line, baseUrl)); - return
; + + const sanitized = resolveUrls(markdown, baseUrl); + + return ( + + {sanitized} + + ); }; diff --git a/src/lib/Markdown/Section.tsx b/src/lib/Markdown/Section.tsx deleted file mode 100644 index fb2933d..0000000 --- a/src/lib/Markdown/Section.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import React from 'react'; -import { Typography } from '@material-ui/core'; -import ContentSection from '../ContentSection/ContentSection'; -import Content from './Content'; -import { ParserPropTypes } from './types'; - -interface PropTypes extends ParserPropTypes { - level?: number; -} - -interface MapperPropTypes extends PropTypes { - SectionComponent: React.FC; -} - -const getHeaderLevel = (header: string): number => { - if (!header) return 0; - let level = 0; - while (header[level] === '#') level += 1; - return level; -}; - -const SectionMapper: React.FC = ({ rawLines, level = 0, SectionComponent }) => { - const children = rawLines - .reduce((sections: string[][], line: string) => { - if (line) { - if (getHeaderLevel(line) === level) sections.push([]); - if (sections.length) sections[sections.length - 1].push(line); - } - return sections; - }, []) - .map(sectionLines => ); - - return <>{children}; -}; - - -const Section: React.FC = ({ rawLines, level = 0 }) => { - const deeperLevelIndex = rawLines.findIndex(line => line.match(`^#{${level + 1},} .*$`)); - const rawContent = rawLines.splice(0, (deeperLevelIndex < 0) ? rawLines.length : deeperLevelIndex); - - if (!level) { - return ( - <> - - - - ); - } - - const sectionName = rawContent.splice(0, 1)[0].slice(level).trim(); - const deeperLevel = getHeaderLevel(rawLines[0]); - return ( - - - - - ); -}; - -export default Section; - diff --git a/src/lib/Markdown/SyntacticSpan.tsx b/src/lib/Markdown/SyntacticSpan.tsx deleted file mode 100644 index 11cc024..0000000 --- a/src/lib/Markdown/SyntacticSpan.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import React from 'react'; -import { Link, makeStyles } from '@material-ui/core'; - -import { lib as emojiLib } from 'emojilib'; - -interface PropTypes { - span: string; -} - -interface RegexPair { - global: RegExp; - local: RegExp; -} - -interface Emoji { - name: string; - char: string; -} - -const enclosureRegex = (e: string): RegexPair => ({ - local: new RegExp(`${e}([^${e}]+)${e}`), - global: new RegExp(`(${e}[^${e}]+${e})`), -}); - -const regex: Record = { - conceal: { - global: /(!?\[.+?\]\(.+?\))(?!])/g, - local: /!?\[(.*\]?.*)\]\((.+?)\)/, - }, - rawLink: { - // eslint-disable-next-line max-len - global: /((?:(?:[A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www\.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)(?:(?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[.!/\\\w]*))?)/, - local: /&^/, - }, - emoji: enclosureRegex(':'), - bold: enclosureRegex('\\*\\*'), - italic: enclosureRegex('\\*'), - code: enclosureRegex('`'), - strikeThrough: enclosureRegex('~~'), -}; - -const splitter = new RegExp(Object.values(regex).map(pair => pair.global.source).join('|')); - -const emojiList: Emoji[] = []; -Object.keys(emojiLib).forEach(name => emojiList.push({ name, char: emojiLib[name].char })); - -const useStyles = makeStyles(theme => ({ - code: { - background: theme.palette.background.default, - borderRadius: theme.spacing(0.5), - padding: theme.spacing(0.5), - fontFamily: 'Monospace', - }, - image: { - maxWidth: '100%', - maxHeight: '100%', - }, -})); - -const SyntacticSpan: React.FC = ({ span }) => { - const classes = useStyles(); - if (!span) return null; - - const matchConceal = regex.conceal.local.exec(span); - if (matchConceal) { - if (span[0] === '!') return {matchConceal[1]}; - return ; - } - - const matchEmoji = span.match(regex.emoji.local); - if (matchEmoji) { - const emoji = emojiList.find(e => e.name === matchEmoji[1]); - return {emoji ? emoji.char : span}; - } - - const matchCode = span.match(regex.code.local); - if (matchCode) return {matchCode[1]}; - - const matchBold = span.match(regex.bold.local); - if (matchBold) return {matchBold[1]}; - - const matchItalic = span.match(regex.italic.local); - if (matchItalic) return {matchItalic[1]}; - - const matchStrikeThrough = span.match(regex.strikeThrough.local); - if (matchStrikeThrough) return {matchStrikeThrough[1]}; - - if (span.match(regex.rawLink.global)) return {span}; - - return <>{span}; -}; - - -export { splitter }; -export default SyntacticSpan; - diff --git a/src/lib/Markdown/Text.tsx b/src/lib/Markdown/Text.tsx deleted file mode 100644 index be715fd..0000000 --- a/src/lib/Markdown/Text.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import React from 'react'; -import SyntacticSpan, { splitter } from './SyntacticSpan'; - -interface PropTypes { - line: string; -} - -const Text: React.FC = ({ line }) => { - return <>{line.split(splitter).map(span => )}; -}; - -export default Text; - -- cgit v1.2.3 From 3037c423c30caaa21d7e07cc91688d7f01fb22ab Mon Sep 17 00:00:00 2001 From: eug-vs Date: Thu, 7 Jan 2021 15:09:18 +0300 Subject: feat!: deprecate ContentSection --- src/index.tsx | 82 +++++++++++++++++++++++++++----------------------------- src/lib/index.ts | 4 ++- 2 files changed, 43 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/index.tsx b/src/index.tsx index 63f7938..9a80262 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -9,7 +9,7 @@ import { import { Benzin, Markdown, - ContentSection, + Heading, } from './lib'; import Header from './demo/Header/Header'; @@ -55,24 +55,23 @@ const CustomPage: React.FC = () => { return ( <> - -

- This should be a link to a valid markdown file. Response should give the file contents. - If you copy README file from GitHub, make sure you provide link to raw view. -

-

- -

- -
+ Render custom markdown document +

+ This should be a link to a valid markdown file. Response should give the file contents. + If you copy README file from GitHub, make sure you provide link to raw view. +

+

+ +

+ ); @@ -91,29 +90,28 @@ const LivePreviewPage: React.FC = ({ setLivePreviewData }) => { return ( <> - -

- Start typing and see your text rendered on the left window! - You can find the list of all Markdown features - {' '} - - here - - . (some of them are yet in progress). - We recommend starting with # Header. -

-

- -

-
+ Markdown live preview +

+ Start typing and see your text rendered on the left window! + You can find the list of all Markdown features + {' '} + + here + + . (some of them are yet in progress). + We recommend starting with # Header. +

+

+ +

); }; diff --git a/src/lib/index.ts b/src/lib/index.ts index 545e6f8..2e6dd9e 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -1,3 +1,5 @@ -export { default as ContentSection } from './ContentSection/ContentSection'; export { default as Benzin } from './Benzin/Benzin'; export { default as Markdown } from './Markdown/Markdown'; +export { default as CodeBlock } from './Markdown/CodeBlock'; +export { default as InlineCode } from './Markdown/InlineCode'; +export { default as Heading } from './Markdown/Heading'; -- cgit v1.2.3 From bc288a43c90ab830019bf077d72081fade76c06e Mon Sep 17 00:00:00 2001 From: eug-vs Date: Thu, 7 Jan 2021 15:26:02 +0300 Subject: feat: add dotfiles instead of spacevim tab --- src/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/index.tsx b/src/index.tsx index 63f7938..2ebe975 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -32,7 +32,7 @@ const Icon = logo; const headerContents = { home: null, - spacevim: null, + dotfiles: null, 'material-ui': null, custom: null, 'live preview': null, @@ -40,8 +40,8 @@ const headerContents = { const pageMap: Record = { home: 'https://raw.githubusercontent.com/eug-vs/react-benzin/develop/README.md', - spacevim: 'https://raw.githubusercontent.com/spacevim/spacevim/master/README.md', 'material-ui': 'https://raw.githubusercontent.com/mui-org/material-ui/master/README.md', + dotfiles: 'https://raw.githubusercontent.com/eug-vs/dotfiles/master/.github/README.md', }; -- cgit v1.2.3 From 4ad1f101101771350b253762c5b02d57df6f4ddd Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sat, 9 Jan 2021 16:06:48 +0300 Subject: feat: use remark-gemoji --- src/lib/Markdown/Markdown.tsx | 11 +++++++++-- src/lib/Markdown/emojilib.d.ts | 2 -- src/lib/Markdown/remark-gemoji.d.ts | 2 ++ src/lib/Markdown/types.ts | 4 ---- 4 files changed, 11 insertions(+), 8 deletions(-) delete mode 100644 src/lib/Markdown/emojilib.d.ts create mode 100644 src/lib/Markdown/remark-gemoji.d.ts delete mode 100644 src/lib/Markdown/types.ts (limited to 'src') diff --git a/src/lib/Markdown/Markdown.tsx b/src/lib/Markdown/Markdown.tsx index 01923f9..955aeda 100644 --- a/src/lib/Markdown/Markdown.tsx +++ b/src/lib/Markdown/Markdown.tsx @@ -1,7 +1,8 @@ import React, { useState, useEffect } from 'react'; +import { Link, Typography } from '@material-ui/core'; import axios from 'axios'; import ReactMarkdown from 'react-markdown'; -import { Link, Typography } from '@material-ui/core'; +import emoji from 'remark-gemoji'; import CodeBlock from './CodeBlock'; import InlineCode from './InlineCode'; @@ -44,7 +45,13 @@ const Markdown: React.FC = ({ data, url }) => { return ( - {sanitized} + + {sanitized} + ); }; diff --git a/src/lib/Markdown/emojilib.d.ts b/src/lib/Markdown/emojilib.d.ts deleted file mode 100644 index cddfeea..0000000 --- a/src/lib/Markdown/emojilib.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -declare module 'emojilib'; - diff --git a/src/lib/Markdown/remark-gemoji.d.ts b/src/lib/Markdown/remark-gemoji.d.ts new file mode 100644 index 0000000..d4b4bf6 --- /dev/null +++ b/src/lib/Markdown/remark-gemoji.d.ts @@ -0,0 +1,2 @@ +declare module 'remark-gemoji'; + diff --git a/src/lib/Markdown/types.ts b/src/lib/Markdown/types.ts deleted file mode 100644 index 0b6f4b6..0000000 --- a/src/lib/Markdown/types.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface ParserPropTypes { - rawLines: string[]; -} - -- cgit v1.2.3 From 53e41901558319e6063fdcbca4f6150101c57f10 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Mon, 11 Jan 2021 22:29:03 +0300 Subject: feat: allow passing variable context --- src/demo/content.md | 17 +++++++++++++++ src/index.tsx | 43 +++++++++++++------------------------ src/lib/Markdown/Markdown.tsx | 27 +++++++++++++---------- src/lib/Markdown/remark-gemoji.d.ts | 2 -- src/lib/Markdown/types.d.ts | 6 ++++++ 5 files changed, 54 insertions(+), 41 deletions(-) create mode 100644 src/demo/content.md delete mode 100644 src/lib/Markdown/remark-gemoji.d.ts create mode 100644 src/lib/Markdown/types.d.ts (limited to 'src') diff --git a/src/demo/content.md b/src/demo/content.md new file mode 100644 index 0000000..ad61d33 --- /dev/null +++ b/src/demo/content.md @@ -0,0 +1,17 @@ +## Markdown +[Markdown file](${url}) *(... +```react +fileName +``` +)* that you can see on the left was parsed and rendered by **BENZIN**! :rocket: +Switch between tabs on the header to explore other markdown templates. :recycle: +Templates on the left are being loaded from the [GitHub](https://github.com), though this pane is generated from plaintext. :pen: +## How do I use this feature? +``` +import Markdown from \'react-benzin\'; +const data = \'# Header\\nHello, *world!*\'; +ReactDOM.render(, document.getElementById(\'root\')); +``` +```react +tryButton +``` diff --git a/src/index.tsx b/src/index.tsx index 9a80262..3f312bb 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -14,6 +14,7 @@ import { import Header from './demo/Header/Header'; import Window from './demo/Window/Window'; +import content from './demo/content.md'; import icon from './assets/icon.svg'; const useStyles = makeStyles(theme => ({ @@ -128,19 +129,6 @@ const App: React.FC = () => { const url = pageMap[page]; const fileName = url?.slice(url.lastIndexOf('/') + 1); - const info = [ - /* eslint-disable max-len */ - `## Markdown\n [Markdown file](${url}) *(...${fileName})* that you can see on the left was parsed and rendered by **BENZIN**! :rocket:`, - 'Switch between tabs on the header to explore other markdown templates. :recycle: ', - 'Templates on the left are being loaded from the [GitHub](https://github.com), though this pane is generated from plaintext. :pen:', - '## How do I use this feature?', - '```', - 'import Markdown from \'react-benzin\';', - 'const data = \'# Header\\nHello, *world!*\';', - 'ReactDOM.render(, document.getElementById(\'root\'));', - '```', - /* eslint-enable max-len */ - ].join('\n'); let primaryWindowContent = ; if (page === 'custom') primaryWindowContent = ; @@ -148,6 +136,19 @@ const App: React.FC = () => { primaryWindowContent = ; } + const tryButton = ( +

+ +

+ ); + return (
{ { (page === 'live preview') ? - : ( - <> - -

- -

- - ) + : }
diff --git a/src/lib/Markdown/Markdown.tsx b/src/lib/Markdown/Markdown.tsx index 955aeda..9bc05a0 100644 --- a/src/lib/Markdown/Markdown.tsx +++ b/src/lib/Markdown/Markdown.tsx @@ -12,6 +12,7 @@ import Image from './Image'; interface PropTypes { data?: string; url?: string; + context?: any; } const resolveUrls = (line: string, baseUrl: string): string => line.replace( @@ -22,15 +23,8 @@ const resolveUrls = (line: string, baseUrl: string): string => line.replace( (match, text, url) => `[${text}](${baseUrl}/${url})`, ); -const renderers = { - heading: Heading, - inlineCode: InlineCode, - code: CodeBlock, - link: Link, - image: Image, -}; -const Markdown: React.FC = ({ data, url }) => { +const Markdown: React.FC = ({ data, url, context = {} }) => { const [markdown, setMarkdown] = useState(data || ''); if (url) axios.get(url).then(response => setMarkdown(response.data)); @@ -43,15 +37,26 @@ const Markdown: React.FC = ({ data, url }) => { const sanitized = resolveUrls(markdown, baseUrl); + const renderers = { + heading: Heading, + inlineCode: InlineCode, + link: Link, + image: Image, + code: ({ language, value }: any) => { + if (language === 'react') return context[value] || null; + return CodeBlock({ value }); + }, + }; + + return ( - {sanitized} - + /> ); }; diff --git a/src/lib/Markdown/remark-gemoji.d.ts b/src/lib/Markdown/remark-gemoji.d.ts deleted file mode 100644 index d4b4bf6..0000000 --- a/src/lib/Markdown/remark-gemoji.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -declare module 'remark-gemoji'; - diff --git a/src/lib/Markdown/types.d.ts b/src/lib/Markdown/types.d.ts new file mode 100644 index 0000000..f39e4f2 --- /dev/null +++ b/src/lib/Markdown/types.d.ts @@ -0,0 +1,6 @@ +declare module 'remark-gemoji'; +declare module '*.md' { + let Markdown: string; + export default Markdown; +} + -- cgit v1.2.3 From e3253a726d4bb71825e392cbde89d05bb3146dc1 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Mon, 11 Jan 2021 22:40:43 +0300 Subject: feat: use inline syntax for context --- src/demo/content.md | 12 ++++-------- src/lib/Markdown/Markdown.tsx | 19 +++++++++++-------- 2 files changed, 15 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/demo/content.md b/src/demo/content.md index ad61d33..41607a9 100644 --- a/src/demo/content.md +++ b/src/demo/content.md @@ -1,9 +1,5 @@ ## Markdown -[Markdown file](${url}) *(... -```react -fileName -``` -)* that you can see on the left was parsed and rendered by **BENZIN**! :rocket: +[Markdown file](${url}) *(...`$fileName`)* that you can see on the left was parsed and rendered by **BENZIN**! :rocket: Switch between tabs on the header to explore other markdown templates. :recycle: Templates on the left are being loaded from the [GitHub](https://github.com), though this pane is generated from plaintext. :pen: ## How do I use this feature? @@ -12,6 +8,6 @@ import Markdown from \'react-benzin\'; const data = \'# Header\\nHello, *world!*\'; ReactDOM.render(, document.getElementById(\'root\')); ``` -```react -tryButton -``` + +`$tryButton` + diff --git a/src/lib/Markdown/Markdown.tsx b/src/lib/Markdown/Markdown.tsx index 9bc05a0..c91bc14 100644 --- a/src/lib/Markdown/Markdown.tsx +++ b/src/lib/Markdown/Markdown.tsx @@ -12,7 +12,7 @@ import Image from './Image'; interface PropTypes { data?: string; url?: string; - context?: any; + context?: Record; } const resolveUrls = (line: string, baseUrl: string): string => line.replace( @@ -34,21 +34,24 @@ const Markdown: React.FC = ({ data, url, context = {} }) => { }, [data, url]); const baseUrl = url?.slice(0, url.lastIndexOf('/')) || ''; - const sanitized = resolveUrls(markdown, baseUrl); + const WrappedInlineCode: React.FC = ({ children }) => { + if (typeof children === 'string' && children?.startsWith('$')) { + const symbol = children.slice(1); + return context[symbol] || null; + } + return {children}; + }; + const renderers = { heading: Heading, - inlineCode: InlineCode, + code: CodeBlock, link: Link, image: Image, - code: ({ language, value }: any) => { - if (language === 'react') return context[value] || null; - return CodeBlock({ value }); - }, + inlineCode: WrappedInlineCode, }; - return ( Date: Mon, 11 Jan 2021 23:15:00 +0300 Subject: fix: resolve eslint errors --- src/lib/Markdown/Markdown.tsx | 1 + src/lib/Markdown/types.d.ts | 1 + 2 files changed, 2 insertions(+) (limited to 'src') diff --git a/src/lib/Markdown/Markdown.tsx b/src/lib/Markdown/Markdown.tsx index c91bc14..4fa6a9a 100644 --- a/src/lib/Markdown/Markdown.tsx +++ b/src/lib/Markdown/Markdown.tsx @@ -12,6 +12,7 @@ import Image from './Image'; interface PropTypes { data?: string; url?: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any context?: Record; } diff --git a/src/lib/Markdown/types.d.ts b/src/lib/Markdown/types.d.ts index f39e4f2..f444cf1 100644 --- a/src/lib/Markdown/types.d.ts +++ b/src/lib/Markdown/types.d.ts @@ -1,5 +1,6 @@ declare module 'remark-gemoji'; declare module '*.md' { + // eslint-disable-next-line import/no-mutable-exports let Markdown: string; export default Markdown; } -- cgit v1.2.3 From d97f845a881901332ba2412c36be8747b50d796e Mon Sep 17 00:00:00 2001 From: eug-vs Date: Thu, 14 Jan 2021 19:42:20 +0300 Subject: feat!: remove ContentSection --- src/lib/ContentSection/ContentSection.tsx | 51 ------------------------------- 1 file changed, 51 deletions(-) delete mode 100644 src/lib/ContentSection/ContentSection.tsx (limited to 'src') diff --git a/src/lib/ContentSection/ContentSection.tsx b/src/lib/ContentSection/ContentSection.tsx deleted file mode 100644 index f18684c..0000000 --- a/src/lib/ContentSection/ContentSection.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import React from 'react'; - -import { - Typography, - Divider, - makeStyles, - useMediaQuery, - Theme, -} from '@material-ui/core'; - - -interface PropTypes { - sectionName: string; - level?: number; -} - -const useStyles = makeStyles(theme => ({ - content: { - [theme.breakpoints.up('md')]: { - padding: theme.spacing(2, 2, 1, 3), - }, - [theme.breakpoints.down('sm')]: { - padding: theme.spacing(2, 0), - }, - marginBottom: theme.spacing(1), - }, -})); - -const ContentSection: React.FC = ({ sectionName, children, level = 0 }) => { - const classes = useStyles(); - const isMobile = useMediaQuery((theme: Theme) => theme.breakpoints.down('sm')); - - let adjustedLevel = level + 2; // Make everything smaller - if (adjustedLevel > 6) adjustedLevel = 6; - - type Variant = 'h3' | 'h4' | 'h5' | 'h6'; - const variant: Variant = `h${adjustedLevel}` as Variant; - - return ( - <> - {sectionName} - - - {children} - - - ); -}; - - -export default ContentSection; -- cgit v1.2.3 From fb6a805f7285a88e485fed52211f0d4631c1e860 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Thu, 14 Jan 2021 19:50:33 +0300 Subject: fix: remove unnecessary escape sequences --- src/demo/content.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/demo/content.md b/src/demo/content.md index 41607a9..01d848f 100644 --- a/src/demo/content.md +++ b/src/demo/content.md @@ -4,9 +4,9 @@ Switch between tabs on the header to explore other markdown templates. :recycle: Templates on the left are being loaded from the [GitHub](https://github.com), though this pane is generated from plaintext. :pen: ## How do I use this feature? ``` -import Markdown from \'react-benzin\'; -const data = \'# Header\\nHello, *world!*\'; -ReactDOM.render(, document.getElementById(\'root\')); +import Markdown from 'react-benzin'; +const data = '# Header\nHello, *world!*'; +ReactDOM.render(, document.getElementById('root')); ``` `$tryButton` -- cgit v1.2.3 From fa16b78695099fe28d233edc8cb6fce67e5e2648 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Thu, 14 Jan 2021 19:51:16 +0300 Subject: refactor: rename data -> source prop --- src/index.tsx | 2 +- src/lib/Markdown/Markdown.tsx | 41 ++++++++++++++++++++++++++--------------- 2 files changed, 27 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/index.tsx b/src/index.tsx index aa786ac..e37e7aa 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -133,7 +133,7 @@ const App: React.FC = () => { let primaryWindowContent = ; if (page === 'custom') primaryWindowContent = ; else if (page === 'live preview') { - primaryWindowContent = ; + primaryWindowContent = ; } const tryButton = ( diff --git a/src/lib/Markdown/Markdown.tsx b/src/lib/Markdown/Markdown.tsx index 4fa6a9a..32732ec 100644 --- a/src/lib/Markdown/Markdown.tsx +++ b/src/lib/Markdown/Markdown.tsx @@ -10,7 +10,7 @@ import Heading from './Heading'; import Image from './Image'; interface PropTypes { - data?: string; + source?: string; url?: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any context?: Record; @@ -24,33 +24,44 @@ const resolveUrls = (line: string, baseUrl: string): string => line.replace( (match, text, url) => `[${text}](${baseUrl}/${url})`, ); +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const WrappedInlineCode = (context: Record): React.FC => ({ children }) => { + if (typeof children === 'string' && children?.startsWith('$')) { + const symbol = children.slice(1); + return context[symbol] || null; + } + return {children}; +}; + +const Markdown: React.FC = ({ + children, + url, + source, + context = {}, +}) => { + const [markdown, setMarkdown] = useState(source || ''); -const Markdown: React.FC = ({ data, url, context = {} }) => { - const [markdown, setMarkdown] = useState(data || ''); + useEffect(() => { + if (url) axios.get(url).then(response => setMarkdown(response.data)); + }, [url]); - if (url) axios.get(url).then(response => setMarkdown(response.data)); + useEffect(() => { + if (source) setMarkdown(source); + }, [source]); useEffect(() => { - if (!url) setMarkdown(data || ''); - }, [data, url]); + if (children && typeof children === 'string') setMarkdown(children); + }, [children]); const baseUrl = url?.slice(0, url.lastIndexOf('/')) || ''; const sanitized = resolveUrls(markdown, baseUrl); - const WrappedInlineCode: React.FC = ({ children }) => { - if (typeof children === 'string' && children?.startsWith('$')) { - const symbol = children.slice(1); - return context[symbol] || null; - } - return {children}; - }; - const renderers = { heading: Heading, code: CodeBlock, link: Link, image: Image, - inlineCode: WrappedInlineCode, + inlineCode: WrappedInlineCode(context), }; return ( -- cgit v1.2.3 From ce028df672325e2efaef2f9dbee05701328b0924 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Thu, 14 Jan 2021 19:54:17 +0300 Subject: feat: allow passing plugins to Markdown --- src/lib/Markdown/Markdown.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib/Markdown/Markdown.tsx b/src/lib/Markdown/Markdown.tsx index 32732ec..c0389dc 100644 --- a/src/lib/Markdown/Markdown.tsx +++ b/src/lib/Markdown/Markdown.tsx @@ -14,6 +14,8 @@ interface PropTypes { url?: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any context?: Record; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + plugins?: any[] } const resolveUrls = (line: string, baseUrl: string): string => line.replace( @@ -38,6 +40,7 @@ const Markdown: React.FC = ({ url, source, context = {}, + plugins = [], }) => { const [markdown, setMarkdown] = useState(source || ''); @@ -69,7 +72,7 @@ const Markdown: React.FC = ({ -- cgit v1.2.3