From eee96f01e29ddb8b95e9429c4e584fe6e7e7faec Mon Sep 17 00:00:00 2001 From: Eug-VS Date: Sat, 8 Feb 2020 15:31:14 +0300 Subject: feat: implement initial markdown component --- src/lib/Markdown/Markdown.tsx | 57 +++++++++++++++++++++++++++++++++++++++++++ src/lib/Markdown/example.md | 50 +++++++++++++++++++++++++++++++++++++ src/lib/index.ts | 1 + 3 files changed, 108 insertions(+) create mode 100644 src/lib/Markdown/Markdown.tsx create mode 100644 src/lib/Markdown/example.md (limited to 'src/lib') diff --git a/src/lib/Markdown/Markdown.tsx b/src/lib/Markdown/Markdown.tsx new file mode 100644 index 0000000..a3ffc38 --- /dev/null +++ b/src/lib/Markdown/Markdown.tsx @@ -0,0 +1,57 @@ +import React from 'react'; + +import ContentSection from '../ContentSection/ContentSection'; + + +interface PropTypes { + data: string; +} + +interface RawLinesPropType { + rawLines: string[]; + level?: number; +} + +const header = (level: number): string => { + return `^#{${level}} .*$`; +}; + +const Content: React.FC = ({ rawLines }) => { + const plainText = rawLines.join(); + return

{plainText}

; +} + +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: any[], 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 }) => { + const rawLines = data.split('\n'); + return +}; + + +export default Markdown; + diff --git a/src/lib/Markdown/example.md b/src/lib/Markdown/example.md new file mode 100644 index 0000000..abc0910 --- /dev/null +++ b/src/lib/Markdown/example.md @@ -0,0 +1,50 @@ +# Getting started +## Installation +You can easily add **BENZIN** to your project with `npm`: +```bash +$ npm install react-benzin +``` +**BENZIN** works best in kick-starting new projects and allows you to focus on the functionality, while all the beauty will be maintained by our library. + +**TIP:** *Create-React-App with Typescript* is your GO-TO in most of the cases. [Learn more.](https://create-react-app.dev/docs/adding-typescript/) + +![Preview screenshot](https://user-images.githubusercontent.com/51545008/73991116-46b04f00-495c-11ea-9733-865bcc6c8807.png) + +You can find a minimal usage example [here](src/index.tsx). + +## Functionality +**BENZIN** provides you with a bunch of cool components that greatly integrate with each other. + +[Explore](src/lib) `src/lib/` folder to see what's available. Documentation is yet to come, but for now you can enjoy type definitons. + +[Chrono-Cube](https://github.com/eug-vs/chrono-cube/) will also be a great example of usage, since it's the actual project which inspired us to create **BENZIN**. + + +# Explore NPM package online +https://www.npmjs.com/package/react-benzin + + +# Development +## Running live demo +To run a live example, clone a repo and execute following commands: +```bash +$ npm i +$ npm start +``` +It's worth noticing that presence of React-App in this repo forces us to split some configurations. For example, we have 2 `Typescript` configs: one for `react-scripts` to run live-demo, and the other one to build *distribution files*. + +## Running tests +```bash +$ npm test +``` +**NOTE**: this command assures that `ESlint` does not throw any warnings and exits with a *non-zero status code* otherwise. That means `CircleCI` tests would fail *even if a single warning is present*. Therefore, you should always locally test your changes before publishing them. + +## Building +We've decided to use `Typescript compiler` to transpile our code, since we think `Babel` is a bit of an overkill here. +```bash +$ npm run build +``` +This command will generate `dist/` folder ready for distribution, which you of course can explore. Note that `tsc` creates type definitions (`.d.ts`) for every corresponding `.js` file. It's very useful because consumers also get access to them. + +## Deploying +Deploying to `npm` is fully automated through **CircleCI**: simply tag a commit as a Release and it will do the job. diff --git a/src/lib/index.ts b/src/lib/index.ts index a41dd39..121c908 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -4,3 +4,4 @@ export { default as ContentSection } from './ContentSection/ContentSection'; export { default as SmartList } from './SmartList/SmartList'; export { default as BenzinThemeProvider } from './BenzinThemeProvider/BenzinThemeProvider'; export { default as Button } from './Button/Button'; +export { default as Markdown } from './Markdown/Markdown'; -- cgit v1.2.3 From a2877c2844825853b8913a07a40f814fc03ac999 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Fri, 3 Apr 2020 03:30:16 +0300 Subject: feat: support Markdown by url --- src/lib/Markdown/Markdown.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'src/lib') diff --git a/src/lib/Markdown/Markdown.tsx b/src/lib/Markdown/Markdown.tsx index a3ffc38..944ac86 100644 --- a/src/lib/Markdown/Markdown.tsx +++ b/src/lib/Markdown/Markdown.tsx @@ -1,10 +1,12 @@ -import React from 'react'; +import React, { useState, useEffect } from 'react'; +import axios from 'axios'; import ContentSection from '../ContentSection/ContentSection'; interface PropTypes { - data: string; + data?: string; + url?: string; } interface RawLinesPropType { @@ -14,7 +16,7 @@ interface RawLinesPropType { const header = (level: number): string => { return `^#{${level}} .*$`; -}; +} const Content: React.FC = ({ rawLines }) => { const plainText = rawLines.join(); @@ -47,9 +49,10 @@ const Level: React.FC = ({ rawLines, level = 0 }) => { ); } -const Markdown: React.FC = ({ data }) => { - const rawLines = data.split('\n'); - return +const Markdown: React.FC = ({ data, url }) => { + const [markdown, setMarkdown] = useState(data || ''); + if (url) axios.get(url).then(response => setMarkdown(response.data)); + return }; -- cgit v1.2.3 From e491abb55723ab20a36ead83320e40627cca8e06 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Fri, 3 Apr 2020 03:37:31 +0300 Subject: fix: correct linting errors :rotating_light: --- src/lib/Markdown/Markdown.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/lib') diff --git a/src/lib/Markdown/Markdown.tsx b/src/lib/Markdown/Markdown.tsx index 944ac86..b3119f1 100644 --- a/src/lib/Markdown/Markdown.tsx +++ b/src/lib/Markdown/Markdown.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState } from 'react'; import axios from 'axios'; import ContentSection from '../ContentSection/ContentSection'; @@ -30,7 +30,7 @@ const Level: React.FC = ({ rawLines, level = 0 }) => { const rawContent = (contentSize > 0) ? rawLines.slice(1, contentSize) : rawLines.slice(1); const rawChildren = rawLines.slice(contentSize); - const childrenLineGroups = rawChildren.reduce((acc: any[], cur: string) => { + 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; -- cgit v1.2.3 From badd3517cd11a68d70fa6ba7cdb1e5afaaf79310 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Fri, 3 Apr 2020 03:49:26 +0300 Subject: feat: add linebreaks --- src/lib/Markdown/Markdown.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lib') diff --git a/src/lib/Markdown/Markdown.tsx b/src/lib/Markdown/Markdown.tsx index b3119f1..332d08c 100644 --- a/src/lib/Markdown/Markdown.tsx +++ b/src/lib/Markdown/Markdown.tsx @@ -19,7 +19,7 @@ const header = (level: number): string => { } const Content: React.FC = ({ rawLines }) => { - const plainText = rawLines.join(); + const plainText = rawLines.map(line =>

{line}

); return

{plainText}

; } -- cgit v1.2.3 From fd0497b855ae03f8f1dfb65edca67ee53431712f Mon Sep 17 00:00:00 2001 From: eug-vs Date: Fri, 3 Apr 2020 04:03:46 +0300 Subject: fix: remove occasional file --- src/lib/Markdown/example.md | 50 --------------------------------------------- 1 file changed, 50 deletions(-) delete mode 100644 src/lib/Markdown/example.md (limited to 'src/lib') diff --git a/src/lib/Markdown/example.md b/src/lib/Markdown/example.md deleted file mode 100644 index abc0910..0000000 --- a/src/lib/Markdown/example.md +++ /dev/null @@ -1,50 +0,0 @@ -# Getting started -## Installation -You can easily add **BENZIN** to your project with `npm`: -```bash -$ npm install react-benzin -``` -**BENZIN** works best in kick-starting new projects and allows you to focus on the functionality, while all the beauty will be maintained by our library. - -**TIP:** *Create-React-App with Typescript* is your GO-TO in most of the cases. [Learn more.](https://create-react-app.dev/docs/adding-typescript/) - -![Preview screenshot](https://user-images.githubusercontent.com/51545008/73991116-46b04f00-495c-11ea-9733-865bcc6c8807.png) - -You can find a minimal usage example [here](src/index.tsx). - -## Functionality -**BENZIN** provides you with a bunch of cool components that greatly integrate with each other. - -[Explore](src/lib) `src/lib/` folder to see what's available. Documentation is yet to come, but for now you can enjoy type definitons. - -[Chrono-Cube](https://github.com/eug-vs/chrono-cube/) will also be a great example of usage, since it's the actual project which inspired us to create **BENZIN**. - - -# Explore NPM package online -https://www.npmjs.com/package/react-benzin - - -# Development -## Running live demo -To run a live example, clone a repo and execute following commands: -```bash -$ npm i -$ npm start -``` -It's worth noticing that presence of React-App in this repo forces us to split some configurations. For example, we have 2 `Typescript` configs: one for `react-scripts` to run live-demo, and the other one to build *distribution files*. - -## Running tests -```bash -$ npm test -``` -**NOTE**: this command assures that `ESlint` does not throw any warnings and exits with a *non-zero status code* otherwise. That means `CircleCI` tests would fail *even if a single warning is present*. Therefore, you should always locally test your changes before publishing them. - -## Building -We've decided to use `Typescript compiler` to transpile our code, since we think `Babel` is a bit of an overkill here. -```bash -$ npm run build -``` -This command will generate `dist/` folder ready for distribution, which you of course can explore. Note that `tsc` creates type definitions (`.d.ts`) for every corresponding `.js` file. It's very useful because consumers also get access to them. - -## Deploying -Deploying to `npm` is fully automated through **CircleCI**: simply tag a commit as a Release and it will do the job. -- cgit v1.2.3 From 464b5fbef2f58cbcd134b7200c5f7c2f904202a0 Mon Sep 17 00:00:00 2001 From: Eug-VS Date: Sat, 4 Apr 2020 20:43:00 +0300 Subject: feat: parse CodeBlocks --- src/lib/Markdown/Markdown.tsx | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'src/lib') diff --git a/src/lib/Markdown/Markdown.tsx b/src/lib/Markdown/Markdown.tsx index 332d08c..8d93437 100644 --- a/src/lib/Markdown/Markdown.tsx +++ b/src/lib/Markdown/Markdown.tsx @@ -18,9 +18,35 @@ const header = (level: number): string => { return `^#{${level}} .*$`; } +const CodeBlock: React.FC<{ rawLines: String[]}> = ({ rawLines }) => { + return ( +

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

+ ); +} + + const Content: React.FC = ({ rawLines }) => { - const plainText = rawLines.map(line =>

{line}

); - return

{plainText}

; + 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 }) => { -- cgit v1.2.3 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/lib') 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 From 0dad2f90bc79bdaa909184c618da5c0473972e0c Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sat, 4 Apr 2020 22:19:46 +0300 Subject: fix: rename types.d.ts -> types.ts --- src/lib/Markdown/types.d.ts | 4 ---- src/lib/Markdown/types.ts | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 src/lib/Markdown/types.d.ts create mode 100644 src/lib/Markdown/types.ts (limited to 'src/lib') diff --git a/src/lib/Markdown/types.d.ts b/src/lib/Markdown/types.d.ts deleted file mode 100644 index 0b6f4b6..0000000 --- a/src/lib/Markdown/types.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface ParserPropTypes { - rawLines: string[]; -} - diff --git a/src/lib/Markdown/types.ts b/src/lib/Markdown/types.ts new file mode 100644 index 0000000..0b6f4b6 --- /dev/null +++ b/src/lib/Markdown/types.ts @@ -0,0 +1,4 @@ +export interface ParserPropTypes { + rawLines: string[]; +} + -- cgit v1.2.3 From a35cdfebf2d8c53c77900fee0826d4a967290e5d Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sun, 5 Apr 2020 01:01:30 +0300 Subject: feat: add Paragraph component --- src/lib/Markdown/Content.tsx | 5 ++-- src/lib/Markdown/Paragraph.tsx | 67 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 src/lib/Markdown/Paragraph.tsx (limited to 'src/lib') diff --git a/src/lib/Markdown/Content.tsx b/src/lib/Markdown/Content.tsx index b7829ed..2a9e2ee 100644 --- a/src/lib/Markdown/Content.tsx +++ b/src/lib/Markdown/Content.tsx @@ -1,6 +1,7 @@ import React from 'react'; import CodeBlock from './CodeBlock'; +import Paragraph from './Paragraph'; import { ParserPropTypes } from './types'; @@ -16,10 +17,10 @@ const Content: React.FC = ({ rawLines }) => { let result; if (denotesCodeBlock(line)) { const closeIndex = rawLines.findIndex(line => denotesCodeBlock(line)); - const codeBlockLines = rawLines.splice(0, closeIndex); + const codeBlockLines = rawLines.splice(0, closeIndex + 1).slice(0, closeIndex); result = } else { - result =

{line}

+ result = } return ( diff --git a/src/lib/Markdown/Paragraph.tsx b/src/lib/Markdown/Paragraph.tsx new file mode 100644 index 0000000..f433cf5 --- /dev/null +++ b/src/lib/Markdown/Paragraph.tsx @@ -0,0 +1,67 @@ +import React from 'react'; + +interface PropTypes { + data: string; +} + +interface Closures { + [key: string]: string; +} + +interface Patterns { + [key: string]: RegExp; +} + +interface Styles { + [key: string]: React.CSSProperties; +} + + +const captureInside = (closure: string): any => { + return new RegExp(closure + '([^' + closure + ']+)' + closure); +} +const capture = (closure: string): any => { + return new RegExp('(' + closure + '[^' + closure + ']+' + closure + ')'); +} + +const closures: Closures = { + inlineCode: '`', + bold: '\\*\\*', +}; + +const styles: Styles = { + inlineCode: { background: '#444444', padding: '4px' }, + bold: { fontWeight: 'bold' }, +}; +const patterns: Patterns = {}; + + +Object.keys(closures).forEach((key: string): void => { + patterns[key] = capture(closures[key]); +}); + +const matcher = new RegExp(Object.values(patterns).map(regex => regex.source).join('|')); + +Object.keys(closures).forEach((key: string): void => { + patterns[key] = captureInside(closures[key]); +}); + + +const SyntaxSpan: React.FC = ({ data }) => { + if (!data) return null; + for (let key in styles) { + const match = data.match(patterns[key]); + if (match) return {match[1]}; + }; + return <>{data}; +} + +const Paragraph: React.FC = ({ data }) => { + let result; + result = data.split(matcher); + result = result.map(span => ); + return

{result}

; +} + +export default Paragraph; + -- cgit v1.2.3 From 208322f596240d23ff8248733f4b196c1baf8a5a Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sun, 5 Apr 2020 02:35:03 +0300 Subject: feat: parse all inline styles --- src/lib/Markdown/Paragraph.tsx | 81 +++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 40 deletions(-) (limited to 'src/lib') diff --git a/src/lib/Markdown/Paragraph.tsx b/src/lib/Markdown/Paragraph.tsx index f433cf5..5ecedfc 100644 --- a/src/lib/Markdown/Paragraph.tsx +++ b/src/lib/Markdown/Paragraph.tsx @@ -4,62 +4,63 @@ interface PropTypes { data: string; } -interface Closures { - [key: string]: string; -} +type RuleName = 'bold' | 'italic' | 'inlineCode' | 'strikeThrough'; -interface Patterns { - [key: string]: RegExp; +interface RuleProperties { + enclosure: string; + style: React.CSSProperties; + pattern?: RegExp; } -interface Styles { - [key: string]: React.CSSProperties; -} +const rules: Record= { // Order matters - lowest property has highest priority + strikeThrough: { + enclosure: '~~', + style: { textDecoration: 'line-through' }, + }, + inlineCode: { + enclosure: '`', + style: { background: '#444444', padding: '4px' }, + }, + italic: { + enclosure: '\\*', + style: { fontStyle: 'italic' }, + }, + bold: { + enclosure: '\\*\\*', + style: { fontWeight: 'bold' }, + }, +}; +const ruleNames = Object.keys(rules) as RuleName[]; -const captureInside = (closure: string): any => { - return new RegExp(closure + '([^' + closure + ']+)' + closure); +const capture = (enclosure: string): RegExp => { + return new RegExp(enclosure + '([^' + enclosure + ']+)' + enclosure); } -const capture = (closure: string): any => { - return new RegExp('(' + closure + '[^' + closure + ']+' + closure + ')'); +const captureSplit = (enclosure: string): string => { + return '(' + enclosure + '[^' + enclosure + ']+' + enclosure + ')'; } -const closures: Closures = { - inlineCode: '`', - bold: '\\*\\*', -}; - -const styles: Styles = { - inlineCode: { background: '#444444', padding: '4px' }, - bold: { fontWeight: 'bold' }, -}; -const patterns: Patterns = {}; - - -Object.keys(closures).forEach((key: string): void => { - patterns[key] = capture(closures[key]); -}); - -const matcher = new RegExp(Object.values(patterns).map(regex => regex.source).join('|')); - -Object.keys(closures).forEach((key: string): void => { - patterns[key] = captureInside(closures[key]); +const ruleSplitPatterns: string[] = []; +ruleNames.forEach(name => { + rules[name].pattern = capture(rules[name].enclosure); + ruleSplitPatterns.push(captureSplit(rules[name].enclosure)); }); +const splitter = new RegExp(ruleSplitPatterns.join('|')); const SyntaxSpan: React.FC = ({ data }) => { if (!data) return null; - for (let key in styles) { - const match = data.match(patterns[key]); - if (match) return {match[1]}; - }; - return <>{data}; + let span = <>{data}; + ruleNames.forEach(name => { + const rule = rules[name]; + const match = data.match(rule.pattern || ''); + if (match) span = {match[1]}; + }); + return span; } const Paragraph: React.FC = ({ data }) => { - let result; - result = data.split(matcher); - result = result.map(span => ); + const result = data.split(splitter).map(span => ); return

{result}

; } -- cgit v1.2.3 From 6087d49a95b6c4164068c219847efc1e70399cb5 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sun, 5 Apr 2020 02:38:47 +0300 Subject: feat: add some paddings --- src/lib/ContentSection/ContentSection.tsx | 2 +- src/lib/Markdown/CodeBlock.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/lib') diff --git a/src/lib/ContentSection/ContentSection.tsx b/src/lib/ContentSection/ContentSection.tsx index 7ff47f9..68ecbca 100644 --- a/src/lib/ContentSection/ContentSection.tsx +++ b/src/lib/ContentSection/ContentSection.tsx @@ -13,7 +13,7 @@ interface PropTypes { const useStyles = makeStyles(theme => ({ content: { - padding: theme.spacing(0, 2, 1, 2), + padding: theme.spacing(1, 2, 1, 3), marginBottom: theme.spacing(1), '& .MuiButton-root': { diff --git a/src/lib/Markdown/CodeBlock.tsx b/src/lib/Markdown/CodeBlock.tsx index e449f92..ee2114e 100644 --- a/src/lib/Markdown/CodeBlock.tsx +++ b/src/lib/Markdown/CodeBlock.tsx @@ -3,7 +3,7 @@ import { ParserPropTypes } from './types'; const CodeBlock: React.FC = ({ rawLines }) => { return ( -

+

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

); -- cgit v1.2.3 From 351cbf596fdda867240d76b632f9d205f343153c Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sun, 5 Apr 2020 05:06:34 +0300 Subject: feat: parse links and images --- src/lib/Markdown/Paragraph.tsx | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) (limited to 'src/lib') diff --git a/src/lib/Markdown/Paragraph.tsx b/src/lib/Markdown/Paragraph.tsx index 5ecedfc..a473142 100644 --- a/src/lib/Markdown/Paragraph.tsx +++ b/src/lib/Markdown/Paragraph.tsx @@ -1,23 +1,25 @@ import React from 'react'; +import { Link } from '@material-ui/core'; interface PropTypes { data: string; } -type RuleName = 'bold' | 'italic' | 'inlineCode' | 'strikeThrough'; +type InlineRuleName = 'bold' | 'italic' | 'code' | 'strikeThrough'; -interface RuleProperties { +interface InlineRuleProperties { enclosure: string; style: React.CSSProperties; pattern?: RegExp; } -const rules: Record= { // Order matters - lowest property has highest priority +const inlineRules: Record= { + // Order matters - lowest property has highest priority strikeThrough: { enclosure: '~~', style: { textDecoration: 'line-through' }, }, - inlineCode: { + code: { enclosure: '`', style: { background: '#444444', padding: '4px' }, }, @@ -31,28 +33,41 @@ const rules: Record= { // Order matters - lowest prop }, }; -const ruleNames = Object.keys(rules) as RuleName[]; +const inlineRuleNames = Object.keys(inlineRules) as InlineRuleName[]; -const capture = (enclosure: string): RegExp => { +const captureInline = (enclosure: string): RegExp => { return new RegExp(enclosure + '([^' + enclosure + ']+)' + enclosure); } -const captureSplit = (enclosure: string): string => { +const captureInlineSplit = (enclosure: string): string => { return '(' + enclosure + '[^' + enclosure + ']+' + enclosure + ')'; } +const concealRegex = /!?\[(.+?)\]\((.+?)\)/; +const concealRegexSplit = /(!?\[.+?\]\(.+?\))/g; +const rawLinkRegex = /((?:(?:[A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www\.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)(?:(?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[.!/\\\w]*))?)/; -const ruleSplitPatterns: string[] = []; -ruleNames.forEach(name => { - rules[name].pattern = capture(rules[name].enclosure); - ruleSplitPatterns.push(captureSplit(rules[name].enclosure)); +const ruleSplitPatterns: string[] = [concealRegexSplit.source, rawLinkRegex.source]; +inlineRuleNames.forEach(name => { + const enclosure = inlineRules[name].enclosure; + inlineRules[name].pattern = captureInline(enclosure); + ruleSplitPatterns.push(captureInlineSplit(enclosure)); }); const splitter = new RegExp(ruleSplitPatterns.join('|')); const SyntaxSpan: React.FC = ({ data }) => { if (!data) return null; + + const conceal = concealRegex.exec(data); + if (conceal) { + if (data[0] === '!') return {conceal[1]}; + return {conceal[1]}; + } + + if (data.match(rawLinkRegex)) return {data}; + let span = <>{data}; - ruleNames.forEach(name => { - const rule = rules[name]; + inlineRuleNames.forEach(name => { + const rule = inlineRules[name]; const match = data.match(rule.pattern || ''); if (match) span = {match[1]}; }); @@ -66,3 +81,4 @@ const Paragraph: React.FC = ({ data }) => { export default Paragraph; + -- cgit v1.2.3 From 0389a542776f8f7fc3bc71a54b0aca7179f6fed3 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sun, 5 Apr 2020 07:44:13 +0300 Subject: refactor: improve Markdown/Section :zap: --- src/lib/Markdown/Section.tsx | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) (limited to 'src/lib') diff --git a/src/lib/Markdown/Section.tsx b/src/lib/Markdown/Section.tsx index c902379..5ae4a10 100644 --- a/src/lib/Markdown/Section.tsx +++ b/src/lib/Markdown/Section.tsx @@ -11,27 +11,33 @@ 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 ChildrenSections: React.FC = ({ rawLines, level = 1 }) => { const childrenSectionLines = rawLines.reduce((sections: string[][], line: string) => { - if (matchHeaderLevel(line, level + 1)) sections.push([]); + if (matchHeaderLevel(line, level)) sections.push([]); if (sections.length) sections[sections.length - 1].push(line); return sections; }, []); - const children = childrenSectionLines.map(sectionLines =>
) + const children = childrenSectionLines.map(sectionLines =>
); + return <> {children} ; +} + +const Section: React.FC = ({ rawLines, level = 0 }) => { + if (!level) { + const beforeMarkdown = rawLines.splice(0, rawLines.findIndex(line => line.match(/^#.+$/g))); + console.log(`This content was found in original .md file but will not be shown: ${beforeMarkdown.join()}`); + while(rawLines[0][level + 1] === '#') level++; + return ; + } + + 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); - return level ? ( - + return ( + - {children} + - ) : ( - <> - {children} - ); } -- cgit v1.2.3 From 21cb0da607e4c0b71f847756e2736cf99b143885 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sun, 5 Apr 2020 08:57:10 +0300 Subject: feat: parse emoji :fire: --- src/lib/Markdown/Paragraph.tsx | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'src/lib') diff --git a/src/lib/Markdown/Paragraph.tsx b/src/lib/Markdown/Paragraph.tsx index a473142..19f8382 100644 --- a/src/lib/Markdown/Paragraph.tsx +++ b/src/lib/Markdown/Paragraph.tsx @@ -1,11 +1,17 @@ import React from 'react'; import { Link } from '@material-ui/core'; +import axios from 'axios'; interface PropTypes { data: string; } -type InlineRuleName = 'bold' | 'italic' | 'code' | 'strikeThrough'; +interface Emoji { + name: string; + char: string; +} + +type InlineRuleName = 'bold' | 'italic' | 'code' | 'strikeThrough' | 'emoji'; interface InlineRuleProperties { enclosure: string; @@ -31,6 +37,10 @@ const inlineRules: Record= { enclosure: '\\*\\*', style: { fontWeight: 'bold' }, }, + emoji: { + enclosure: ':', + style: {}, + } }; const inlineRuleNames = Object.keys(inlineRules) as InlineRuleName[]; @@ -54,6 +64,11 @@ inlineRuleNames.forEach(name => { const splitter = new RegExp(ruleSplitPatterns.join('|')); +const emojiList: Emoji[] = []; +axios.get('https://unpkg.com/emojilib@2.4.0/emojis.json').then(response => { + Object.keys(response.data).forEach(name => emojiList.push({ name, char: response.data[name].char })); +}); + const SyntaxSpan: React.FC = ({ data }) => { if (!data) return null; @@ -69,7 +84,12 @@ const SyntaxSpan: React.FC = ({ data }) => { inlineRuleNames.forEach(name => { const rule = inlineRules[name]; const match = data.match(rule.pattern || ''); - if (match) span = {match[1]}; + if (match) { + if (name === 'emoji') { + const emoji = emojiList.find(emoji => emoji.name === match[1]); + span = {emoji ? emoji.char : ''}; + } else span = {match[1]}; + } }); return span; } -- cgit v1.2.3 From f67d9b549f8cba939a0420c16207a9e71b03be37 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sun, 5 Apr 2020 09:06:02 +0300 Subject: feat: change sectionName size respectively --- src/lib/ContentSection/ContentSection.tsx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src/lib') diff --git a/src/lib/ContentSection/ContentSection.tsx b/src/lib/ContentSection/ContentSection.tsx index 68ecbca..ba8b882 100644 --- a/src/lib/ContentSection/ContentSection.tsx +++ b/src/lib/ContentSection/ContentSection.tsx @@ -9,11 +9,12 @@ import { interface PropTypes { sectionName: string; + level?: number; } const useStyles = makeStyles(theme => ({ content: { - padding: theme.spacing(1, 2, 1, 3), + padding: theme.spacing(2, 2, 1, 3), marginBottom: theme.spacing(1), '& .MuiButton-root': { @@ -22,12 +23,18 @@ const useStyles = makeStyles(theme => ({ }, })); -const ContentSection: React.FC = ({ sectionName, children }) => { +const ContentSection: React.FC = ({ sectionName, children, level = 0 }) => { const classes = useStyles(); + level += 2; // Make everything smaller + if (level > 6) level = 6; + + type Variant = 'h3' | 'h4' | 'h5' | 'h6'; + const variant: Variant = 'h' + level as Variant; + return ( <> - {sectionName} + {sectionName} {children} -- cgit v1.2.3 From bc8e9919925d9d7ee640e8091aebe9596f9e89eb Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sun, 5 Apr 2020 11:06:56 +0300 Subject: refactor: refine Section component --- src/lib/Markdown/Section.tsx | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'src/lib') diff --git a/src/lib/Markdown/Section.tsx b/src/lib/Markdown/Section.tsx index 5ae4a10..5ce8954 100644 --- a/src/lib/Markdown/Section.tsx +++ b/src/lib/Markdown/Section.tsx @@ -7,14 +7,19 @@ interface PropTypes extends ParserPropTypes { level?: number; } -const matchHeaderLevel = (line: string, level: number): boolean => { - return line.match(`^#{${level}} .*$`) !== null; +const getHeaderLevel = (header: string): number => { + if (!header) return 0; + let level = 0; + while(header[level] === '#') level++; + return level; } -const ChildrenSections: React.FC = ({ rawLines, level = 1 }) => { +const ChildrenSections: React.FC = ({ rawLines, level = 0 }) => { const childrenSectionLines = rawLines.reduce((sections: string[][], line: string) => { - if (matchHeaderLevel(line, level)) sections.push([]); - if (sections.length) sections[sections.length - 1].push(line); + if (line) { + if (getHeaderLevel(line) === level) sections.push([]); + if (sections.length) sections[sections.length - 1].push(line); + } return sections; }, []); const children = childrenSectionLines.map(sectionLines =>
); @@ -22,21 +27,17 @@ const ChildrenSections: React.FC = ({ rawLines, level = 1 }) => { } const Section: React.FC = ({ rawLines, level = 0 }) => { - if (!level) { - const beforeMarkdown = rawLines.splice(0, rawLines.findIndex(line => line.match(/^#.+$/g))); - console.log(`This content was found in original .md file but will not be shown: ${beforeMarkdown.join()}`); - while(rawLines[0][level + 1] === '#') level++; - return ; - } + const deeperLevelIndex = rawLines.findIndex(line => line.match(`^#{${level + 1},} .*$`)); + const rawContent = rawLines.splice(0, (deeperLevelIndex < 0) ? rawLines.length : deeperLevelIndex); - 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); + if (!level) return ; + const sectionName = rawContent.splice(0, 1)[0].slice(level).trim(); + const deeperLevel = getHeaderLevel(rawLines[0]); return ( - + ); } -- cgit v1.2.3 From 39e1d32c669545ccc30e0d424323c6a01317c4be Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sun, 5 Apr 2020 12:56:41 +0300 Subject: refactor: move some logic to InlineSyntax.tsx --- src/lib/Markdown/CodeBlock.tsx | 2 +- src/lib/Markdown/Content.tsx | 2 +- src/lib/Markdown/InlineSyntax.tsx | 81 ++++++++++++++++++++++++++++++ src/lib/Markdown/Paragraph.tsx | 100 ++------------------------------------ src/lib/Markdown/types.ts | 4 ++ 5 files changed, 91 insertions(+), 98 deletions(-) create mode 100644 src/lib/Markdown/InlineSyntax.tsx (limited to 'src/lib') diff --git a/src/lib/Markdown/CodeBlock.tsx b/src/lib/Markdown/CodeBlock.tsx index ee2114e..2718647 100644 --- a/src/lib/Markdown/CodeBlock.tsx +++ b/src/lib/Markdown/CodeBlock.tsx @@ -3,7 +3,7 @@ import { ParserPropTypes } from './types'; const CodeBlock: React.FC = ({ rawLines }) => { return ( -

+

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

); diff --git a/src/lib/Markdown/Content.tsx b/src/lib/Markdown/Content.tsx index 2a9e2ee..d0a2193 100644 --- a/src/lib/Markdown/Content.tsx +++ b/src/lib/Markdown/Content.tsx @@ -20,7 +20,7 @@ const Content: React.FC = ({ rawLines }) => { const codeBlockLines = rawLines.splice(0, closeIndex + 1).slice(0, closeIndex); result = } else { - result = + result = } return ( diff --git a/src/lib/Markdown/InlineSyntax.tsx b/src/lib/Markdown/InlineSyntax.tsx new file mode 100644 index 0000000..bf5669d --- /dev/null +++ b/src/lib/Markdown/InlineSyntax.tsx @@ -0,0 +1,81 @@ +import React from 'react'; +import { Link } from '@material-ui/core'; +import axios from 'axios'; + +import { InlineParserPropTypes } from './types'; + +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: { + 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[] = []; +axios.get('https://unpkg.com/emojilib@2.4.0/emojis.json').then(response => { + Object.keys(response.data).forEach(name => emojiList.push({ name, char: response.data[name].char })); +}); + + +const InlineSyntax: React.FC = ({ line }) => { + if (!line) return null; + + const matchConceal = regex.conceal.local.exec(line); + if (matchConceal) { + if (line[0] === '!') return {matchConceal[1]}; + return {matchConceal[1]}; + } + + const matchEmoji = line.match(regex.emoji.local); + if (matchEmoji) { + const emoji = emojiList.find(emoji => emoji.name === matchEmoji[1]); + return {emoji ? emoji.char : line}; + } + + const matchCode = line.match(regex.code.local); + if (matchCode) return {matchCode[1]}; + + const matchBold = line.match(regex.bold.local); + if (matchBold) return {matchBold[1]}; + + const matchItalic = line.match(regex.italic.local); + if (matchItalic) return {matchItalic[1]}; + + const matchStrikeThrough = line.match(regex.strikeThrough.local); + if (matchStrikeThrough) return {matchStrikeThrough[1]}; + + if (line.match(regex.rawLink.global)) return {line}; + + return <>{line}; +} + + +export { splitter }; +export default InlineSyntax; + diff --git a/src/lib/Markdown/Paragraph.tsx b/src/lib/Markdown/Paragraph.tsx index 19f8382..f46199e 100644 --- a/src/lib/Markdown/Paragraph.tsx +++ b/src/lib/Markdown/Paragraph.tsx @@ -1,101 +1,9 @@ import React from 'react'; -import { Link } from '@material-ui/core'; -import axios from 'axios'; +import { InlineParserPropTypes } from './types'; +import InlineSyntax, { splitter } from './InlineSyntax'; -interface PropTypes { - data: string; -} - -interface Emoji { - name: string; - char: string; -} - -type InlineRuleName = 'bold' | 'italic' | 'code' | 'strikeThrough' | 'emoji'; - -interface InlineRuleProperties { - enclosure: string; - style: React.CSSProperties; - pattern?: RegExp; -} - -const inlineRules: Record= { - // Order matters - lowest property has highest priority - strikeThrough: { - enclosure: '~~', - style: { textDecoration: 'line-through' }, - }, - code: { - enclosure: '`', - style: { background: '#444444', padding: '4px' }, - }, - italic: { - enclosure: '\\*', - style: { fontStyle: 'italic' }, - }, - bold: { - enclosure: '\\*\\*', - style: { fontWeight: 'bold' }, - }, - emoji: { - enclosure: ':', - style: {}, - } -}; - -const inlineRuleNames = Object.keys(inlineRules) as InlineRuleName[]; - -const captureInline = (enclosure: string): RegExp => { - return new RegExp(enclosure + '([^' + enclosure + ']+)' + enclosure); -} -const captureInlineSplit = (enclosure: string): string => { - return '(' + enclosure + '[^' + enclosure + ']+' + enclosure + ')'; -} -const concealRegex = /!?\[(.+?)\]\((.+?)\)/; -const concealRegexSplit = /(!?\[.+?\]\(.+?\))/g; -const rawLinkRegex = /((?:(?:[A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www\.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)(?:(?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[.!/\\\w]*))?)/; - -const ruleSplitPatterns: string[] = [concealRegexSplit.source, rawLinkRegex.source]; -inlineRuleNames.forEach(name => { - const enclosure = inlineRules[name].enclosure; - inlineRules[name].pattern = captureInline(enclosure); - ruleSplitPatterns.push(captureInlineSplit(enclosure)); -}); - -const splitter = new RegExp(ruleSplitPatterns.join('|')); - -const emojiList: Emoji[] = []; -axios.get('https://unpkg.com/emojilib@2.4.0/emojis.json').then(response => { - Object.keys(response.data).forEach(name => emojiList.push({ name, char: response.data[name].char })); -}); - -const SyntaxSpan: React.FC = ({ data }) => { - if (!data) return null; - - const conceal = concealRegex.exec(data); - if (conceal) { - if (data[0] === '!') return {conceal[1]}; - return {conceal[1]}; - } - - if (data.match(rawLinkRegex)) return {data}; - - let span = <>{data}; - inlineRuleNames.forEach(name => { - const rule = inlineRules[name]; - const match = data.match(rule.pattern || ''); - if (match) { - if (name === 'emoji') { - const emoji = emojiList.find(emoji => emoji.name === match[1]); - span = {emoji ? emoji.char : ''}; - } else span = {match[1]}; - } - }); - return span; -} - -const Paragraph: React.FC = ({ data }) => { - const result = data.split(splitter).map(span => ); +const Paragraph: React.FC = ({ line }) => { + const result = line.split(splitter).map(span => ); return

{result}

; } diff --git a/src/lib/Markdown/types.ts b/src/lib/Markdown/types.ts index 0b6f4b6..8fb28ed 100644 --- a/src/lib/Markdown/types.ts +++ b/src/lib/Markdown/types.ts @@ -1,3 +1,7 @@ +export interface InlineParserPropTypes { + line: string; +} + export interface ParserPropTypes { rawLines: string[]; } -- cgit v1.2.3 From 62a543258a111f0f45be74b6ec3d887e15f67376 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sun, 5 Apr 2020 14:18:45 +0300 Subject: feat: beautify CodeBlock --- src/lib/Markdown/CodeBlock.tsx | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'src/lib') diff --git a/src/lib/Markdown/CodeBlock.tsx b/src/lib/Markdown/CodeBlock.tsx index 2718647..cbb3078 100644 --- a/src/lib/Markdown/CodeBlock.tsx +++ b/src/lib/Markdown/CodeBlock.tsx @@ -1,11 +1,23 @@ import React from 'react'; import { ParserPropTypes } from './types'; +import { Paper } from '@material-ui/core'; + +import { makeStyles } from '@material-ui/core/styles'; + +const useStyles = makeStyles(theme => ({ + root: { + background: theme.palette.background.default, + padding: theme.spacing(2), + overflowX: 'auto', + }, +})); const CodeBlock: React.FC = ({ rawLines }) => { + const classes = useStyles(); return ( -

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

+ ); } -- cgit v1.2.3 From 1a00cd504ff60f1749327ebc3896a4641d28670e Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sun, 5 Apr 2020 16:31:28 +0300 Subject: feat: install emojilib, beautify inline code --- src/lib/Markdown/CodeBlock.tsx | 1 + src/lib/Markdown/InlineSyntax.tsx | 29 +++++++++++++++++++++-------- 2 files changed, 22 insertions(+), 8 deletions(-) (limited to 'src/lib') diff --git a/src/lib/Markdown/CodeBlock.tsx b/src/lib/Markdown/CodeBlock.tsx index cbb3078..c4478eb 100644 --- a/src/lib/Markdown/CodeBlock.tsx +++ b/src/lib/Markdown/CodeBlock.tsx @@ -9,6 +9,7 @@ const useStyles = makeStyles(theme => ({ background: theme.palette.background.default, padding: theme.spacing(2), overflowX: 'auto', + fontFamily: 'Monospace', }, })); diff --git a/src/lib/Markdown/InlineSyntax.tsx b/src/lib/Markdown/InlineSyntax.tsx index bf5669d..48c0374 100644 --- a/src/lib/Markdown/InlineSyntax.tsx +++ b/src/lib/Markdown/InlineSyntax.tsx @@ -1,7 +1,8 @@ import React from 'react'; -import { Link } from '@material-ui/core'; -import axios from 'axios'; +import { Link, makeStyles } from '@material-ui/core'; +// @ts-ignore-next-line; +import { lib as emojiLib } from 'emojilib'; import { InlineParserPropTypes } from './types'; interface RegexPair { @@ -38,17 +39,29 @@ const regex: Record = { const splitter = new RegExp(Object.values(regex).map(pair => pair.global.source).join('|')); const emojiList: Emoji[] = []; -axios.get('https://unpkg.com/emojilib@2.4.0/emojis.json').then(response => { - Object.keys(response.data).forEach(name => emojiList.push({ name, char: response.data[name].char })); -}); - +Object.keys(emojiLib).forEach(name => emojiList.push({ name, char: emojiLib[name].char })); +console.log({emojiList}) + +const useStyles = makeStyles(theme => ({ + code: { + background: theme.palette.background.default, + borderRadius: theme.spacing(.5), + padding: theme.spacing(.5), + fontFamily: 'Monospace', + }, + image: { + maxWidth: '100%', + maxHeight: '100%' + }, +})); const InlineSyntax: React.FC = ({ line }) => { + const classes = useStyles(); if (!line) return null; const matchConceal = regex.conceal.local.exec(line); if (matchConceal) { - if (line[0] === '!') return {matchConceal[1]}; + if (line[0] === '!') return {matchConceal[1]}; return {matchConceal[1]}; } @@ -59,7 +72,7 @@ const InlineSyntax: React.FC = ({ line }) => { } const matchCode = line.match(regex.code.local); - if (matchCode) return {matchCode[1]}; + if (matchCode) return {matchCode[1]}; const matchBold = line.match(regex.bold.local); if (matchBold) return {matchBold[1]}; -- cgit v1.2.3 From 5abf2d02bd4d11097b2650861195cf605e42bbf7 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sun, 5 Apr 2020 16:32:44 +0300 Subject: fix: update markdown on hook --- src/lib/Markdown/Markdown.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/lib') diff --git a/src/lib/Markdown/Markdown.tsx b/src/lib/Markdown/Markdown.tsx index aee96e9..09ad54a 100644 --- a/src/lib/Markdown/Markdown.tsx +++ b/src/lib/Markdown/Markdown.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import axios from 'axios'; import Section from './Section'; @@ -10,6 +10,11 @@ interface PropTypes { const Markdown: React.FC = ({ data, url }) => { const [markdown, setMarkdown] = useState(data || ''); + + useEffect(() => { + if (!url) setMarkdown(data || ''); + }, [data, url]); + if (url) axios.get(url).then(response => setMarkdown(response.data)); return
}; -- cgit v1.2.3 From b26b6c045419893bc375616d8f186bd41c5ccca1 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sun, 5 Apr 2020 17:51:58 +0300 Subject: fix: declare emojilib module --- src/lib/Markdown/InlineSyntax.tsx | 1 - 1 file changed, 1 deletion(-) (limited to 'src/lib') diff --git a/src/lib/Markdown/InlineSyntax.tsx b/src/lib/Markdown/InlineSyntax.tsx index 48c0374..53cdaf0 100644 --- a/src/lib/Markdown/InlineSyntax.tsx +++ b/src/lib/Markdown/InlineSyntax.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { Link, makeStyles } from '@material-ui/core'; -// @ts-ignore-next-line; import { lib as emojiLib } from 'emojilib'; import { InlineParserPropTypes } from './types'; -- cgit v1.2.3 From eda4a1dceeb3d8db5ce47a555f098dbaa1deb996 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sun, 5 Apr 2020 20:02:05 +0300 Subject: feat: parse dotted lists --- src/lib/Markdown/Content.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src/lib') diff --git a/src/lib/Markdown/Content.tsx b/src/lib/Markdown/Content.tsx index d0a2193..593b9e9 100644 --- a/src/lib/Markdown/Content.tsx +++ b/src/lib/Markdown/Content.tsx @@ -2,11 +2,16 @@ import React from 'react'; import CodeBlock from './CodeBlock'; import Paragraph from './Paragraph'; +import InlineSyntax from './InlineSyntax'; import { ParserPropTypes } from './types'; const denotesCodeBlock = (line: string): boolean => { - return line.slice(0, 3) === '```'; + return line.match(/^```.*$/) !== null; +} + +const denotesDottedList = (line: string): boolean => { + return line.match(/^ ?- .*$/) !== null; } const Content: React.FC = ({ rawLines }) => { @@ -19,6 +24,11 @@ const Content: React.FC = ({ rawLines }) => { const closeIndex = rawLines.findIndex(line => denotesCodeBlock(line)); const codeBlockLines = rawLines.splice(0, closeIndex + 1).slice(0, closeIndex); result = + } else if (denotesDottedList(line)) { + const closeIndex = rawLines.findIndex(line => !denotesDottedList(line)); + const dottedListLines = rawLines.splice(0, closeIndex).slice(0, closeIndex); + dottedListLines.unshift(line); + result =
    {dottedListLines.map(li =>
  • )}
; } else { result = } @@ -28,7 +38,7 @@ const Content: React.FC = ({ rawLines }) => { { result } - ) + ); } export default Content; -- cgit v1.2.3 From b6e58c0f8eebb0447e5330b983ec387dbf2a59c0 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sun, 5 Apr 2020 20:42:25 +0300 Subject: feat: parse html :rocket: --- src/lib/Markdown/Content.tsx | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'src/lib') diff --git a/src/lib/Markdown/Content.tsx b/src/lib/Markdown/Content.tsx index 593b9e9..1f0fcfc 100644 --- a/src/lib/Markdown/Content.tsx +++ b/src/lib/Markdown/Content.tsx @@ -14,28 +14,45 @@ const denotesDottedList = (line: string): boolean => { return line.match(/^ ?- .*$/) !== null; } +const denotesOpenHtmlTag = (line: string): string => { + const regex = /<([^/\s]*)[^<]*[^/]>/g; + const match = regex.exec(line); + return match ? match[1] : ''; +} + +const denotesClosingHtmlTag = (line: string, tag: string): boolean => { + const regex = new RegExp(``); + return line.match(regex) !== null; +} + const Content: React.FC = ({ rawLines }) => { if (!rawLines.length) return null; const line = rawLines.splice(0, 1)[0]; - let result; + let buffer; if (denotesCodeBlock(line)) { const closeIndex = rawLines.findIndex(line => denotesCodeBlock(line)); const codeBlockLines = rawLines.splice(0, closeIndex + 1).slice(0, closeIndex); - result = + buffer = } else if (denotesDottedList(line)) { const closeIndex = rawLines.findIndex(line => !denotesDottedList(line)); const dottedListLines = rawLines.splice(0, closeIndex).slice(0, closeIndex); dottedListLines.unshift(line); - result =
    {dottedListLines.map(li =>
  • )}
; + buffer =
    {dottedListLines.map(li =>
  • )}
; + } else if (denotesOpenHtmlTag(line)) { + const tag = denotesOpenHtmlTag(line); + const closeIndex = rawLines.findIndex(line => denotesClosingHtmlTag(line, tag)); + const htmlLines = rawLines.splice(0, closeIndex + 1).slice(0, closeIndex); + htmlLines.unshift(line); + buffer =
; } else { - result = + buffer = } return ( <> - { result } + { buffer } ); -- cgit v1.2.3 From 1f67a4e15b9ab10f8ecba2ee93e6a4c44e3c71ec Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sun, 5 Apr 2020 21:10:50 +0300 Subject: fix: use
 in CodeBlock

---
 src/lib/Markdown/CodeBlock.tsx | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

(limited to 'src/lib')

diff --git a/src/lib/Markdown/CodeBlock.tsx b/src/lib/Markdown/CodeBlock.tsx
index c4478eb..5b8edec 100644
--- a/src/lib/Markdown/CodeBlock.tsx
+++ b/src/lib/Markdown/CodeBlock.tsx
@@ -7,9 +7,10 @@ import { makeStyles } from '@material-ui/core/styles';
 const useStyles = makeStyles(theme => ({
   root: {
     background: theme.palette.background.default,
-    padding: theme.spacing(2),
+    padding: theme.spacing(1),
     overflowX: 'auto',
     fontFamily: 'Monospace',
+    scrollbarColor: 'auto'
   },
 }));
 
@@ -17,7 +18,7 @@ const CodeBlock: React.FC = ({ rawLines }) => {
   const classes = useStyles();
   return (
     
-      {rawLines.map(line => <> {line} 
)} + {rawLines.map(line =>
{line}
)}
); } -- cgit v1.2.3 From 09f8c6865fb9a7e239cc907e313db44cccb7b5e8 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sun, 5 Apr 2020 21:57:13 +0300 Subject: feat: Paragraph -> Text, parse selfClosingHtml --- src/lib/Markdown/Content.tsx | 30 +++++++++++++++++++++++------- src/lib/Markdown/Paragraph.tsx | 12 ------------ src/lib/Markdown/Text.tsx | 10 ++++++++++ 3 files changed, 33 insertions(+), 19 deletions(-) delete mode 100644 src/lib/Markdown/Paragraph.tsx create mode 100644 src/lib/Markdown/Text.tsx (limited to 'src/lib') diff --git a/src/lib/Markdown/Content.tsx b/src/lib/Markdown/Content.tsx index 1f0fcfc..e27b63f 100644 --- a/src/lib/Markdown/Content.tsx +++ b/src/lib/Markdown/Content.tsx @@ -1,7 +1,7 @@ import React from 'react'; import CodeBlock from './CodeBlock'; -import Paragraph from './Paragraph'; +import Text from './Text'; import InlineSyntax from './InlineSyntax'; import { ParserPropTypes } from './types'; @@ -14,17 +14,22 @@ const denotesDottedList = (line: string): boolean => { return line.match(/^ ?- .*$/) !== null; } -const denotesOpenHtmlTag = (line: string): string => { +const denotesOpenHtml= (line: string): string => { const regex = /<([^/\s]*)[^<]*[^/]>/g; const match = regex.exec(line); return match ? match[1] : ''; } -const denotesClosingHtmlTag = (line: string, tag: string): boolean => { +const denotesClosingHtml= (line: string, tag: string): boolean => { const regex = new RegExp(``); return line.match(regex) !== null; } +const denotesSelfClosingHtml = (line: string): any => { + const regex = /(<[^/\s]*[^<]*\/>)/g; + return line.match(regex); +} + const Content: React.FC = ({ rawLines }) => { if (!rawLines.length) return null; @@ -40,14 +45,25 @@ const Content: React.FC = ({ rawLines }) => { const dottedListLines = rawLines.splice(0, closeIndex).slice(0, closeIndex); dottedListLines.unshift(line); buffer =
    {dottedListLines.map(li =>
  • )}
; - } else if (denotesOpenHtmlTag(line)) { - const tag = denotesOpenHtmlTag(line); - const closeIndex = rawLines.findIndex(line => denotesClosingHtmlTag(line, tag)); + } else if (denotesOpenHtml(line)) { + const tag = denotesOpenHtml(line); + const closeIndex = rawLines.findIndex(line => denotesClosingHtml(line, tag)); const htmlLines = rawLines.splice(0, closeIndex + 1).slice(0, closeIndex); htmlLines.unshift(line); buffer =
; + } else if (denotesSelfClosingHtml(line) !== null) { + const match = denotesSelfClosingHtml(line)[0]; + const [before, after] = line.split(match); + console.log({ line, match, before, after}); + buffer = ( + <> + +
+ + + ); } else { - buffer = + buffer =

} return ( diff --git a/src/lib/Markdown/Paragraph.tsx b/src/lib/Markdown/Paragraph.tsx deleted file mode 100644 index f46199e..0000000 --- a/src/lib/Markdown/Paragraph.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; -import { InlineParserPropTypes } from './types'; -import InlineSyntax, { splitter } from './InlineSyntax'; - -const Paragraph: React.FC = ({ line }) => { - const result = line.split(splitter).map(span => ); - return

{result}

; -} - -export default Paragraph; - - diff --git a/src/lib/Markdown/Text.tsx b/src/lib/Markdown/Text.tsx new file mode 100644 index 0000000..b989476 --- /dev/null +++ b/src/lib/Markdown/Text.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { InlineParserPropTypes } from './types'; +import InlineSyntax, { splitter } from './InlineSyntax'; + +const Text: React.FC = ({ line }) => { + return <>{line.split(splitter).map(span => )}; +} + +export default Text; + -- cgit v1.2.3 From 828946eb02bdfaa7ec5631f1e854881f874f7b7e Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sun, 5 Apr 2020 22:06:54 +0300 Subject: refactor: rename InlineSyntax -> SyntacticSpan --- src/lib/Markdown/Content.tsx | 3 +- src/lib/Markdown/InlineSyntax.tsx | 93 ------------------------------------ src/lib/Markdown/SyntacticSpan.tsx | 96 ++++++++++++++++++++++++++++++++++++++ src/lib/Markdown/Text.tsx | 11 +++-- 4 files changed, 104 insertions(+), 99 deletions(-) delete mode 100644 src/lib/Markdown/InlineSyntax.tsx create mode 100644 src/lib/Markdown/SyntacticSpan.tsx (limited to 'src/lib') diff --git a/src/lib/Markdown/Content.tsx b/src/lib/Markdown/Content.tsx index e27b63f..caac91c 100644 --- a/src/lib/Markdown/Content.tsx +++ b/src/lib/Markdown/Content.tsx @@ -2,7 +2,6 @@ import React from 'react'; import CodeBlock from './CodeBlock'; import Text from './Text'; -import InlineSyntax from './InlineSyntax'; import { ParserPropTypes } from './types'; @@ -44,7 +43,7 @@ const Content: React.FC = ({ rawLines }) => { const closeIndex = rawLines.findIndex(line => !denotesDottedList(line)); const dottedListLines = rawLines.splice(0, closeIndex).slice(0, closeIndex); dottedListLines.unshift(line); - buffer =
    {dottedListLines.map(li =>
  • )}
; + buffer =
    {dottedListLines.map(li =>
  • )}
; } else if (denotesOpenHtml(line)) { const tag = denotesOpenHtml(line); const closeIndex = rawLines.findIndex(line => denotesClosingHtml(line, tag)); diff --git a/src/lib/Markdown/InlineSyntax.tsx b/src/lib/Markdown/InlineSyntax.tsx deleted file mode 100644 index 53cdaf0..0000000 --- a/src/lib/Markdown/InlineSyntax.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import React from 'react'; -import { Link, makeStyles } from '@material-ui/core'; - -import { lib as emojiLib } from 'emojilib'; -import { InlineParserPropTypes } from './types'; - -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: { - 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 })); -console.log({emojiList}) - -const useStyles = makeStyles(theme => ({ - code: { - background: theme.palette.background.default, - borderRadius: theme.spacing(.5), - padding: theme.spacing(.5), - fontFamily: 'Monospace', - }, - image: { - maxWidth: '100%', - maxHeight: '100%' - }, -})); - -const InlineSyntax: React.FC = ({ line }) => { - const classes = useStyles(); - if (!line) return null; - - const matchConceal = regex.conceal.local.exec(line); - if (matchConceal) { - if (line[0] === '!') return {matchConceal[1]}; - return {matchConceal[1]}; - } - - const matchEmoji = line.match(regex.emoji.local); - if (matchEmoji) { - const emoji = emojiList.find(emoji => emoji.name === matchEmoji[1]); - return {emoji ? emoji.char : line}; - } - - const matchCode = line.match(regex.code.local); - if (matchCode) return {matchCode[1]}; - - const matchBold = line.match(regex.bold.local); - if (matchBold) return {matchBold[1]}; - - const matchItalic = line.match(regex.italic.local); - if (matchItalic) return {matchItalic[1]}; - - const matchStrikeThrough = line.match(regex.strikeThrough.local); - if (matchStrikeThrough) return {matchStrikeThrough[1]}; - - if (line.match(regex.rawLink.global)) return {line}; - - return <>{line}; -} - - -export { splitter }; -export default InlineSyntax; - diff --git a/src/lib/Markdown/SyntacticSpan.tsx b/src/lib/Markdown/SyntacticSpan.tsx new file mode 100644 index 0000000..299bf87 --- /dev/null +++ b/src/lib/Markdown/SyntacticSpan.tsx @@ -0,0 +1,96 @@ +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: { + 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 })); +console.log({emojiList}) + +const useStyles = makeStyles(theme => ({ + code: { + background: theme.palette.background.default, + borderRadius: theme.spacing(.5), + padding: theme.spacing(.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 {matchConceal[1]}; + } + + const matchEmoji = span.match(regex.emoji.local); + if (matchEmoji) { + const emoji = emojiList.find(emoji => emoji.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 index b989476..e287dee 100644 --- a/src/lib/Markdown/Text.tsx +++ b/src/lib/Markdown/Text.tsx @@ -1,9 +1,12 @@ import React from 'react'; -import { InlineParserPropTypes } from './types'; -import InlineSyntax, { splitter } from './InlineSyntax'; +import SyntacticSpan, { splitter } from './SyntacticSpan'; -const Text: React.FC = ({ line }) => { - return <>{line.split(splitter).map(span => )}; +interface PropTypes { + line: string; +} + +const Text: React.FC = ({ line }) => { + return <>{line.split(splitter).map(span => )}; } export default Text; -- cgit v1.2.3 From 43d65a56bbe91de967fa2ff86b25ec216bfd5ce1 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sun, 5 Apr 2020 22:16:02 +0300 Subject: style: fix linting errors :rotating_light: --- src/lib/Markdown/Content.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/lib') diff --git a/src/lib/Markdown/Content.tsx b/src/lib/Markdown/Content.tsx index caac91c..aaea100 100644 --- a/src/lib/Markdown/Content.tsx +++ b/src/lib/Markdown/Content.tsx @@ -24,7 +24,7 @@ const denotesClosingHtml= (line: string, tag: string): boolean => { return line.match(regex) !== null; } -const denotesSelfClosingHtml = (line: string): any => { +const denotesSelfClosingHtml = (line: string): string[] | null => { const regex = /(<[^/\s]*[^<]*\/>)/g; return line.match(regex); } @@ -44,14 +44,14 @@ const Content: React.FC = ({ rawLines }) => { const dottedListLines = rawLines.splice(0, closeIndex).slice(0, closeIndex); dottedListLines.unshift(line); buffer =
    {dottedListLines.map(li =>
  • )}
; - } else if (denotesOpenHtml(line)) { - const tag = denotesOpenHtml(line); + } else if ((buffer = denotesOpenHtml(line))) { + const tag = buffer; const closeIndex = rawLines.findIndex(line => denotesClosingHtml(line, tag)); const htmlLines = rawLines.splice(0, closeIndex + 1).slice(0, closeIndex); htmlLines.unshift(line); buffer =
; - } else if (denotesSelfClosingHtml(line) !== null) { - const match = denotesSelfClosingHtml(line)[0]; + } else if ((buffer = denotesSelfClosingHtml(line)) !== null) { + const match = buffer[0]; const [before, after] = line.split(match); console.log({ line, match, before, after}); buffer = ( -- cgit v1.2.3 From 181129f0a99350f2731293dc179b37c9f4eb9abd Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sun, 5 Apr 2020 22:27:28 +0300 Subject: fix: remove unused type :wastebasket: --- src/lib/Markdown/types.ts | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src/lib') diff --git a/src/lib/Markdown/types.ts b/src/lib/Markdown/types.ts index 8fb28ed..0b6f4b6 100644 --- a/src/lib/Markdown/types.ts +++ b/src/lib/Markdown/types.ts @@ -1,7 +1,3 @@ -export interface InlineParserPropTypes { - line: string; -} - export interface ParserPropTypes { rawLines: string[]; } -- cgit v1.2.3 From e9c6eb6be709db76002c41e5bf7d13654493d0a8 Mon Sep 17 00:00:00 2001 From: eug-vs Date: Sun, 5 Apr 2020 22:47:04 +0300 Subject: build: move emojilib declaration to separate file --- src/lib/Markdown/emojilib.d.ts | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/lib/Markdown/emojilib.d.ts (limited to 'src/lib') diff --git a/src/lib/Markdown/emojilib.d.ts b/src/lib/Markdown/emojilib.d.ts new file mode 100644 index 0000000..cddfeea --- /dev/null +++ b/src/lib/Markdown/emojilib.d.ts @@ -0,0 +1,2 @@ +declare module 'emojilib'; + -- cgit v1.2.3