-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #168 from fjcalzado/feature/#156_Real_time_preview…
…_markdown Feature/#156 real time preview markdown
- Loading branch information
Showing
24 changed files
with
1,016 additions
and
111 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
.droppable { | ||
margin-top: 5px; | ||
margin-bottom: 15px; | ||
border: 2px dashed #ccc; | ||
height: 200px; | ||
display: flex; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,2 @@ | ||
import { MarkDownViewerComponent } from './markdownViewerComponent'; | ||
|
||
export { | ||
MarkDownViewerComponent | ||
}; | ||
export { MarkDownViewerComponent } from './markdownViewerComponent'; | ||
export { mapOffsetToLine, mapLineToOffset, SOURCE_LINE_CLASSNAME } from './syncScroll'; |
63 changes: 42 additions & 21 deletions
63
src/common/components/markdownViewer/markdownViewerComponent.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,54 @@ | ||
import * as React from 'react'; | ||
import { marksy } from 'marksy'; | ||
import * as ReactDOM from 'react-dom'; | ||
import { withRouter } from 'react-router'; | ||
import { CreateMarkdownRender, Mdr } from './render'; | ||
|
||
const compile = marksy({ | ||
// TODO: extract into a new <DynamicLink /> that analyze "href" and render a <Link /> or <a /> | ||
a: ({ target, children, ...other }) => ( | ||
<a target="_self" {...other}>{children}</a> | ||
), | ||
}); | ||
/** | ||
* TODO: | ||
* Custom rule to analyze "href" and render a <Link /> (react router) or <a /> | ||
*/ | ||
|
||
export interface MarkDownViewerComponentProps { | ||
interface Props { | ||
content: string; | ||
registerRef?: (ref: HTMLElement) => void; | ||
className?: string; | ||
location?: any; // Router HOC injected. | ||
} | ||
|
||
const getMarkDownChildren = (content: string): React.ReactNode => { | ||
let childrenComponent: React.ReactNode = null; | ||
interface State { | ||
mdr: Mdr; | ||
} | ||
|
||
class MarkDownViewer extends React.Component<Props, State> { | ||
constructor(props) { | ||
super(props); | ||
|
||
if (content) { | ||
childrenComponent = compile(content).tree; | ||
this.state = { | ||
mdr: CreateMarkdownRender({routerLocation: props.location ? props.location.pathname : ''}), | ||
}; | ||
} | ||
|
||
return childrenComponent; | ||
}; | ||
private markdownToHTML = () => { | ||
return { | ||
__html: this.state.mdr.render(this.props.content || ''), | ||
}; | ||
} | ||
|
||
export const MarkDownViewerComponent: React.StatelessComponent<MarkDownViewerComponentProps> = ({ content }) => { | ||
return ( | ||
<div> | ||
{getMarkDownChildren(content)} | ||
</div> | ||
); | ||
public render() { | ||
const {className = ''} = this.props; | ||
return( | ||
<div className={className} ref={this.props.registerRef || (() => {})} | ||
dangerouslySetInnerHTML={this.markdownToHTML()} // See Footnote [1]. | ||
/> | ||
); | ||
} | ||
}; | ||
|
||
MarkDownViewerComponent.displayName = 'MarkDownViewerComponent'; | ||
const MarkDownViewerComponent = withRouter(MarkDownViewer); | ||
export { MarkDownViewerComponent, Props as MarkDownViewerComponentProps } | ||
|
||
// [1] WARNING: This conversion from plain HTML to JSX with | ||
// dangerouslySetInnerHTML could be unsafe (script injection, XSS) | ||
// depending whether markdown engine blocks malicious code or not. | ||
// Markdonw-it is supposed to be XSS safe, but if you plan to | ||
// change engine, ensure safety first! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export { CreateMarkdownRender, Mdr, MdrFactory, MdrSetup } from './markdownRender'; | ||
export { MdrOptions } from './markdownRenderOptions'; | ||
export { MdrCodeStyle } from './markdownRenderCodeStyle'; |
50 changes: 50 additions & 0 deletions
50
src/common/components/markdownViewer/render/markdownRender.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { MarkdownIt as Mdr } from 'markdown-it'; | ||
import * as MdrObject from 'markdown-it'; | ||
import * as mdrPluginAbbr from 'markdown-it-abbr'; | ||
import * as mdrPluginEmoji from 'markdown-it-emoji'; | ||
import * as mdrPluginFootnote from 'markdown-it-footnote'; | ||
import * as mdrPluginIns from 'markdown-it-ins'; | ||
import * as mdrPluginMark from 'markdown-it-mark'; | ||
import * as mdrPluginSub from 'markdown-it-sub'; | ||
import * as mdrPluginSup from 'markdown-it-sup'; | ||
import * as mdrPluginCheckbox from 'markdown-it-checkbox'; | ||
import { loadCustomRules } from './markdownRenderRules'; | ||
import { MdrOptions, defaultOptions, codeHighlighter } from './markdownRenderOptions'; | ||
import { MdrCodeStyle, loadCodeStyle, defaultCodeStyle } from './markdownRenderCodeStyle'; | ||
|
||
interface MdrSetup { | ||
routerLocation: string; | ||
options?: MdrOptions; | ||
codeStyle?: MdrCodeStyle; | ||
} | ||
|
||
type MdrFactory = (setupParams: MdrSetup) => Mdr; | ||
|
||
// Markdown Render Factory. Create render instance and set it up. | ||
const CreateMarkdownRender: MdrFactory = ({ | ||
routerLocation, | ||
options = defaultOptions, | ||
codeStyle = defaultCodeStyle}) => { | ||
// Create instance with options+highlighter & load plugins. | ||
const mdr = new MdrObject({ | ||
...options, | ||
highlight: (str, lang) => codeHighlighter(mdr, str, lang), | ||
}).use(mdrPluginAbbr) | ||
.use(mdrPluginEmoji) | ||
.use(mdrPluginFootnote) | ||
.use(mdrPluginIns) | ||
.use(mdrPluginMark) | ||
.use(mdrPluginSub) | ||
.use(mdrPluginSup) | ||
.use(mdrPluginCheckbox); | ||
|
||
// Load custom rules. | ||
loadCustomRules(mdr, routerLocation); | ||
|
||
// Load code highlight style. | ||
loadCodeStyle(codeStyle); | ||
|
||
return mdr; | ||
}; | ||
|
||
export { CreateMarkdownRender, MdrFactory, MdrSetup, Mdr } |
92 changes: 92 additions & 0 deletions
92
src/common/components/markdownViewer/render/markdownRenderCodeStyle.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
// List of available code styles. | ||
enum MdrCodeStyle { | ||
agate = 'agate', | ||
androidstudio = 'androidstudio', | ||
arduinoLight = 'arduino-light', | ||
arta = 'arta', | ||
ascetic = 'ascetic', | ||
atelierCaveDark = 'atelier-cave-dark', | ||
atelierCaveLight = 'atelier-cave-light', | ||
atelierDuneDark = 'atelier-dune-dark', | ||
atelierDuneLight = 'atelier-dune-light', | ||
atelierEstuaryDark = 'atelier-estuary-dark', | ||
atelierEstuaryLight = 'atelier-estuary-light', | ||
atelierForestDark = 'atelier-forest-dark', | ||
atelierForestLight = 'atelier-forest-light', | ||
atelierHeathDark = 'atelier-heath-dark', | ||
atelierHeathLight = 'atelier-heath-light', | ||
atelierLakesideDark = 'atelier-lakeside-dark', | ||
atelierLakesideLight = 'atelier-lakeside-light', | ||
atelierPlateauDark = 'atelier-plateau-dark', | ||
atelierPlateauLight = 'atelier-plateau-light', | ||
atelierSavannaDark = 'atelier-savanna-dark', | ||
atelierSavannaLight = 'atelier-savanna-light', | ||
atelierSeasideDark = 'atelier-seaside-dark', | ||
atelierSeasideLight = 'atelier-seaside-light', | ||
atelierSulphurpoolDark = 'atelier-sulphurpool-dark', | ||
atelierSulphurpoolLight = 'atelier-sulphurpool-light', | ||
atomOneDark = 'atom-one-dark', | ||
atomOneLight = 'atom-one-light', | ||
brownPaper = 'brown-paper', | ||
codepenEmbed = 'codepen-embed', | ||
colorBrewer = 'color-brewer', | ||
darcula = 'darcula', | ||
dark = 'dark', | ||
darkula = 'darkula', | ||
default = 'default', | ||
docco = 'docco', | ||
dracula = 'dracula', | ||
far = 'far', | ||
foundation = 'foundation', | ||
githubGist = 'github-gist', | ||
github = 'github', | ||
googlecode = 'googlecode', | ||
grayscale = 'grayscale', | ||
gruvboxDark = 'gruvbox-dark', | ||
gruvboxLight = 'gruvbox-light', | ||
hopscotch = 'hopscotch', | ||
hybrid = 'hybrid', | ||
idea = 'idea', | ||
irBlack = 'ir-black', | ||
kimbieDark = 'kimbie.dark', | ||
kimbieLight = 'kimbie.light', | ||
magula = 'magula', | ||
monoBlue = 'mono-blue', | ||
monokaiSublime = 'monokai-sublime', | ||
monokai = 'monokai', | ||
obsidian = 'obsidian', | ||
ocean = 'ocean', | ||
paraisoDark = 'paraiso-dark', | ||
paraisoLight = 'paraiso-light', | ||
pojoaque = 'pojoaque', | ||
purebasic = 'purebasic', | ||
qtcreator_dark = 'qtcreator_dark', | ||
qtcreator_light = 'qtcreator_light', | ||
railscasts = 'railscasts', | ||
rainbow = 'rainbow', | ||
routeros = 'routeros', | ||
schoolBook = 'school-book', | ||
solarizedDark = 'solarized-dark', | ||
solarizedLight = 'solarized-light', | ||
sunburst = 'sunburst', | ||
tomorrowNightNlue = 'tomorrow-night-blue', | ||
tomorrowNightNright = 'tomorrow-night-bright', | ||
tomorrowNightEighties = 'tomorrow-night-eighties', | ||
tomorrowNight = 'tomorrow-night', | ||
tomorrow = 'tomorrow', | ||
vs = 'vs', | ||
vs2015 = 'vs2015', | ||
xcode = 'xcode', | ||
xt256 = 'xt256', | ||
zenburn = 'zenburn', | ||
} | ||
|
||
// Change here code style by default. | ||
const defaultCodeStyle = MdrCodeStyle.atomOneLight; | ||
|
||
// Code style dynamic loader. | ||
const loadCodeStyle = (style: MdrCodeStyle) => { | ||
return require(`highlight.js/styles/${style}.css`); | ||
}; | ||
|
||
export { MdrCodeStyle, loadCodeStyle, defaultCodeStyle } |
35 changes: 35 additions & 0 deletions
35
src/common/components/markdownViewer/render/markdownRenderOptions.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { MarkdownIt as Mdr, Options as MdrOptions } from 'markdown-it'; | ||
import highlightjs from 'highlight.js/lib/highlight'; | ||
|
||
// Markdown Render options by default. | ||
const defaultOptions: MdrOptions = { | ||
html: false, // Enable HTML tags in source. This could be unsafe if enabled (XSS). | ||
xhtmlOut: false, // Use '/' to close single tags (<br />) | ||
breaks: false, // Convert '\n' in paragraphs into <br> | ||
langPrefix: 'language-', // CSS language prefix for fenced blocks | ||
linkify: true, // autoconvert URL-like texts to links | ||
// Enable some language-neutral replacements + quotes beautification | ||
typographer: true, | ||
|
||
// Double + single quotes replacement pairs, when typographer enabled, | ||
// and smartquotes on. Could be either a String or an Array. | ||
// | ||
// For example, you can use '«»„“' for Russian, '„“‚‘' for German, | ||
// and ['«\xA0', '\xA0»', '‹\xA0', '\xA0›'] for French (including nbsp). | ||
quotes: '\u201c\u201d\u2018\u2019', /* “”‘’ */ | ||
}; | ||
|
||
// Markdown Render code highlighter. | ||
const codeHighlighter = (mdr: Mdr, str, lang) => { | ||
const highlighter = () => { | ||
if (lang && highlightjs.getLanguage(lang)) { | ||
try { | ||
return highlightjs.highlight(lang, str, true).value; | ||
} catch (__) {} | ||
} | ||
return mdr.utils.escapeHtml(str); | ||
}; | ||
return '<pre class="hljs"><code>' + highlighter() + '</code></pre>'; | ||
}; | ||
|
||
export { MdrOptions, defaultOptions, codeHighlighter } |
Oops, something went wrong.