diff options
author | Eug-VS <eug-vs@keemail.me> | 2020-04-04 22:05:40 +0300 |
---|---|---|
committer | Eug-VS <eug-vs@keemail.me> | 2020-04-04 22:05:40 +0300 |
commit | bdcc2edb38fb0e57604fa12d25b2a4b478261e18 (patch) | |
tree | 71aaedf7f4500cfcab9bd4f344b326dadd71d392 /src/lib | |
parent | 464b5fbef2f58cbcd134b7200c5f7c2f904202a0 (diff) | |
download | react-benzin-bdcc2edb38fb0e57604fa12d25b2a4b478261e18.tar.gz |
refactor: structurize Markdown component :recycle:
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/Markdown/CodeBlock.tsx | 13 | ||||
-rw-r--r-- | src/lib/Markdown/Content.tsx | 34 | ||||
-rw-r--r-- | src/lib/Markdown/Markdown.tsx | 71 | ||||
-rw-r--r-- | src/lib/Markdown/Section.tsx | 39 | ||||
-rw-r--r-- | src/lib/Markdown/types.d.ts | 4 |
5 files changed, 92 insertions, 69 deletions
diff --git a/src/lib/Markdown/CodeBlock.tsx b/src/lib/Markdown/CodeBlock.tsx new file mode 100644 index 0000000..e449f92 --- /dev/null +++ b/src/lib/Markdown/CodeBlock.tsx @@ -0,0 +1,13 @@ +import React from 'react'; +import { ParserPropTypes } from './types'; + +const CodeBlock: React.FC<ParserPropTypes> = ({ rawLines }) => { + return ( + <p style={{background: '#444444'}}> + {rawLines.map(line => <> {line} <br/> </>)} + </p> + ); +} + +export default CodeBlock; + diff --git a/src/lib/Markdown/Content.tsx b/src/lib/Markdown/Content.tsx new file mode 100644 index 0000000..b7829ed --- /dev/null +++ b/src/lib/Markdown/Content.tsx @@ -0,0 +1,34 @@ +import React from 'react'; + +import CodeBlock from './CodeBlock'; +import { ParserPropTypes } from './types'; + + +const denotesCodeBlock = (line: string): boolean => { + return line.slice(0, 3) === '```'; +} + +const Content: React.FC<ParserPropTypes> = ({ rawLines }) => { + if (!rawLines.length) return null; + + const line = rawLines.splice(0, 1)[0]; + + let result; + if (denotesCodeBlock(line)) { + const closeIndex = rawLines.findIndex(line => denotesCodeBlock(line)); + const codeBlockLines = rawLines.splice(0, closeIndex); + result = <CodeBlock rawLines={codeBlockLines} /> + } else { + result = <p> {line} </p> + } + + return ( + <> + { result } + <Content rawLines={rawLines} /> + </> + ) +} + +export default Content; + diff --git a/src/lib/Markdown/Markdown.tsx b/src/lib/Markdown/Markdown.tsx index 8d93437..aee96e9 100644 --- a/src/lib/Markdown/Markdown.tsx +++ b/src/lib/Markdown/Markdown.tsx @@ -1,84 +1,17 @@ import React, { useState } from 'react'; import axios from 'axios'; -import ContentSection from '../ContentSection/ContentSection'; - +import Section from './Section'; interface PropTypes { data?: string; url?: string; } -interface RawLinesPropType { - rawLines: string[]; - level?: number; -} - -const header = (level: number): string => { - return `^#{${level}} .*$`; -} - -const CodeBlock: React.FC<{ rawLines: String[]}> = ({ rawLines }) => { - return ( - <p style={{background: '#444444'}}> - {rawLines.map(line => <> {line} <br/> </>)} - </p> - ); -} - - -const Content: React.FC<RawLinesPropType> = ({ rawLines }) => { - if (!rawLines.length) return <></>; - const line = rawLines[0]; - const otherLines = rawLines.slice(1); - if (line.slice(0, 3) === '```') { - const closeIndex = otherLines.findIndex(line => line.slice(0, 3) === '```'); - console.log({ line, otherLines, closeIndex }); - return ( - <> - <CodeBlock rawLines={otherLines.slice(0, closeIndex)} /> - <Content rawLines={otherLines.slice(closeIndex + 1)} /> - </> - ) - } - return ( - <> - <p> {line} </p> - <Content rawLines={rawLines.slice(1)} /> - </> - ) -} - -const Level: React.FC<RawLinesPropType> = ({ rawLines, level = 0 }) => { - const name = rawLines[0].slice(level); - const contentSize = rawLines.findIndex(line => line.match(header(level + 1))); - - const rawContent = (contentSize > 0) ? rawLines.slice(1, contentSize) : rawLines.slice(1); - const rawChildren = rawLines.slice(contentSize); - - const childrenLineGroups = rawChildren.reduce((acc: string[][], cur: string) => { - if (cur.match(header(level + 1))) acc.push([]); - if (acc.length) acc[acc.length - 1].push(cur); - return acc; - }, []); - const children = childrenLineGroups.map(lineGroup => <Level rawLines={lineGroup} level={level + 1}/>) - - return level ? ( - <ContentSection sectionName={name}> - <Content rawLines={rawContent} /> - {children} - </ContentSection> - ) : ( - <> - {children} - </> - ); -} - const Markdown: React.FC<PropTypes> = ({ data, url }) => { const [markdown, setMarkdown] = useState<string>(data || ''); if (url) axios.get(url).then(response => setMarkdown(response.data)); - return <Level rawLines={markdown.split('\n')} /> + return <Section rawLines={markdown.split('\n')} /> }; diff --git a/src/lib/Markdown/Section.tsx b/src/lib/Markdown/Section.tsx new file mode 100644 index 0000000..c902379 --- /dev/null +++ b/src/lib/Markdown/Section.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import ContentSection from '../ContentSection/ContentSection'; +import Content from './Content'; +import { ParserPropTypes } from './types'; + +interface PropTypes extends ParserPropTypes { + level?: number; +} + +const matchHeaderLevel = (line: string, level: number): boolean => { + return line.match(`^#{${level}} .*$`) !== null; +} + +const Section: React.FC<PropTypes> = ({ rawLines, level = 0 }) => { + const sectionName = rawLines.splice(0, 1)[0].slice(level).trim(); + const contentSize = rawLines.findIndex(line => matchHeaderLevel(line, level + 1)); + const rawContent = rawLines.splice(0, (contentSize < 0) ? rawLines.length : contentSize); + + const childrenSectionLines = rawLines.reduce((sections: string[][], line: string) => { + if (matchHeaderLevel(line, level + 1)) sections.push([]); + if (sections.length) sections[sections.length - 1].push(line); + return sections; + }, []); + const children = childrenSectionLines.map(sectionLines => <Section rawLines={sectionLines} level={level + 1}/>) + + return level ? ( + <ContentSection sectionName={sectionName}> + <Content rawLines={rawContent} /> + {children} + </ContentSection> + ) : ( + <> + {children} + </> + ); +} + +export default Section; + diff --git a/src/lib/Markdown/types.d.ts b/src/lib/Markdown/types.d.ts new file mode 100644 index 0000000..0b6f4b6 --- /dev/null +++ b/src/lib/Markdown/types.d.ts @@ -0,0 +1,4 @@ +export interface ParserPropTypes { + rawLines: string[]; +} + |