From bdcc2edb38fb0e57604fa12d25b2a4b478261e18 Mon Sep 17 00:00:00 2001 From: Eug-VS Date: Sat, 4 Apr 2020 22:05:40 +0300 Subject: refactor: structurize Markdown component :recycle: --- src/lib/Markdown/CodeBlock.tsx | 13 ++++++++ src/lib/Markdown/Content.tsx | 34 ++++++++++++++++++++ src/lib/Markdown/Markdown.tsx | 71 ++---------------------------------------- src/lib/Markdown/Section.tsx | 39 +++++++++++++++++++++++ src/lib/Markdown/types.d.ts | 4 +++ 5 files changed, 92 insertions(+), 69 deletions(-) create mode 100644 src/lib/Markdown/CodeBlock.tsx create mode 100644 src/lib/Markdown/Content.tsx create mode 100644 src/lib/Markdown/Section.tsx create mode 100644 src/lib/Markdown/types.d.ts (limited to 'src') 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 = ({ rawLines }) => { + return ( +

+ {rawLines.map(line => <> {line}
)} +

+ ); +} + +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 = ({ 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 = + } else { + result =

{line}

+ } + + return ( + <> + { result } + + + ) +} + +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 ( -

- {rawLines.map(line => <> {line}
)} -

- ); -} - - -const Content: React.FC = ({ 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 ( - <> - - - - ) - } - return ( - <> -

{line}

- - - ) -} - -const Level: React.FC = ({ 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 => ) - - return level ? ( - - - {children} - - ) : ( - <> - {children} - - ); -} - const Markdown: React.FC = ({ data, url }) => { const [markdown, setMarkdown] = useState(data || ''); if (url) axios.get(url).then(response => setMarkdown(response.data)); - return + return
}; 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 = ({ 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 =>
) + + return level ? ( + + + {children} + + ) : ( + <> + {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[]; +} + -- cgit v1.2.3