body{
background: none;
color: dimgray;
height: 100vh;
font-family: Verdana, Geneva, sans-serif;
}
a{
text-decoration: none;
}
.navbarContainer{
top:0;
right:0;
left:0;
position:fixed;
min-height:40px;
margin-bottom:20px;
z-index:1000;
background:silver;
border-radius:3px;
box-shadow: 0 0 5px 2px dimgray;
display: flex;
font-family: sans-serif;
font-size: 1em;
line-height: 1.3em;
padding:0;
justify-content:space-between;
}
.navbarContainer a{
color: dimgray;
}
.navLeft, .navRight{
display: flex;
}
.navLeft a, .navRight a{
padding: 8px 12px 0px 12px;
}
.navLeft a:hover, .navRight a:hover{
background: dimgray;
color:white;
border-bottom: solid 1px gray;
border-radius: 3px;
}
.mainContent{
position: absolute;
display: flex;
flex-direction: column;
top: 60px;
width: 90%;
margin: 0 5% 0 5%;
}
.uiBox{
max-width: 95%;
border: solid 1px black;
border-top: ridge 2px white;
box-shadow: 0px 3px 4px 3px dimgray;
margin: 0 0 20px 0;
padding: 5px 5px 5px 5px;
}
.codeBox{
height: 480px;
background: black;
color: lime;
}
.domBox{
min-height: 300px;
}
code{
background: whitesmoke;
}
@media (max-width: 610px){
.navRight .navDrop{
display: block;
}
.dropMenu{
position: absolute;
right: 4px;
top: 40px;
z-index: 1000;
display: flex;
flex-direction: column;
background: silver;
margin-top: 5px;
box-shadow: 0 0 4px 2px gray;
}
.dropMenu a{
color: dimgray;
min-height: 30px;
font-family: sans-serif;
font-size: 1em;
line-height: 1em;
padding: 9px 12px 0px 12px;
text-align: center;
}
.dropMenu a:hover{
background: dimgray;
color: white;
}
}
// IMPORT FUNCTIONS FOR REACT AND REDUX
const render = ReactDOM.render;
// Initialize Marked JS
const MarkUp = new marked.Renderer;
MarkUp.link = function(h,i,t){
return `<a href='${h}' target='_blank'>${t}</a>`;
}
marked.setOptions({
renderer: MarkUp,
breaks: true,
xhtml: true
})
//const MarkUp = new marked.Renderer();
// GLOBALS
const LOGO = {'Markdown Preview':'#'};
const SITELINKS = {
'One': '#',
'Two': '#',
'Three': '#'
};
const DEFAULT_TEXT=`
BASIC GUIDELINES:
# Heading
## Sub-heading
[Link to React Website](https://reactjs.org/)
Here is some inline \`<code></code>\`
A code-block:
\`\`\`
function(code){
return {myCode: code};
}
\`\`\`
Unordered List
* United States
* Alaska
* Anchorage
Ordered list
1. Dogs
a. Terriers
b. Hounds
2. Cats
3. Mice
Text: _italic_ and **bold**
> Here is a block quote
Images:

`
/*
CALLS A PROVIDED FUNCTION ON EACH PROPERTY OF THE PROVIDED OBJECT; RETURNS AN ARRAY
ARGUMENTS: {{}, function(key, value, index)}
*/
function mapObject(obj, callback) {
return Object.keys(obj).map((k, i)=>{
return callback(k, obj[k], i);
});
}
// REACT
/* LINKS FOR NAVBAR LOCATIONS
PROPS: {places: {}}
*/
const NavPlaces = (props) =>{
return mapObject(props.places, function (key, value, iter) {
return (<a
onClick={value}
key={key+iter.toString()}>{key}
</a>);
});
}
NavPlaces.propTypes={
places: PropTypes.objectOf(PropTypes.string).isRequired
}
/* LEFT NAVBAR
PROPS: {sWidth: #, places: {}}
*/
const LeftNav = (props) =>{
return(<div id={'dispLeft'} className={'navLeft'}>
<NavPlaces places={LOGO} />
{props.sWidth>610 ? <NavPlaces places={props.places} />:null}
</div>);
}
LeftNav.propTypes={
sWidth: PropTypes.number.isRequired,
places: PropTypes.objectOf(PropTypes.string).isRequired
}
/* SOCIAL NETWORK LINKS
PROPS: {link: string, name: string}
*/
const SocialLink = (props)=>{
return <a href={props.link}><i className={'fa fa-'+props.name}></i></a>
}
SocialLink.propTypes={
link: PropTypes.string,
name: PropTypes.name
}
/* RIGHT NAVBAR
PROPS: {menuHandler: function}
*/
const RightNav = (props)=>{
return(<div id={'dispRight'} className={'navRight'}>
{/*<SocialLink link={'#'} name={'github'}/>
<SocialLink link={'#'} name={'twitter'}/>
<SocialLink link={'#'} name={'linkedin'}/>*/}
{props.sWidth<611 ?
(<a href='#' id={'responseMenu'} class={'navDrop'} onClick={props.menuHandler}>
<i class='fa fa-bars'></i>
</a>):
null}
</div>);
}
RightNav.propTypes={
menuHandler: PropTypes.func.isRequired
}
/* NAVBAR CONTAINER FOR LEFT AND RIGHT NAVBARS
PROPS: {logo: {}, places: {}, sWidth: #, menuHandler:function}
*/
const NavParent = (props)=>{
return(<nav className={'navbarContainer'}>
<LeftNav logo={props.logo} places={props.places} sWidth={props.sWidth}/>
<RightNav sWidth={props.sWidth} menuHandler={props.menuHandler} />
</nav>
);
}
NavParent.propTypes={
logo: PropTypes.objectOf(PropTypes.string).isRequired,
places: PropTypes.objectOf(PropTypes.string).isRequired,
sWidth: PropTypes.number.isRequired,
menuHandler: PropTypes.func.isRequired
}
/* NAVBAR DROPDOWN COMPONENT
PROPS: {places:{}, menuHandler:function}
*/
const ResponsiveNav = (props)=>{
return(<div className={'dropMenu'} onClick={props.menuHandler}>
<NavPlaces places={props.places}/>
</div>
);
}
ResponsiveNav.propTypes={
places: PropTypes.objectOf(PropTypes.string).isRequired,
menuHandler: PropTypes.func.isRequired
}
/* NAVBAR PARENT COMPONENT
CURRENTLY NO PROPS
*/
class Navbar extends React.Component {
constructor(props){
super(props);
this.state={
sWidth: window.innerWidth,
respondMenu: false
};
this.updateWidth=this.updateWidth.bind(this);
this.menuHandler=this.menuHandler.bind(this);
}
componentDidMount(){
window.addEventListener('resize', this.updateWidth);
}
updateWidth(){
this.setState({sWidth: window.innerWidth});
}
menuHandler(){
this.setState(p=>({respondMenu:!p.respondMenu}));
}
render(){
return(<div>
<NavParent
logo={LOGO}
places={this.props.places}
sWidth={this.state.sWidth}
menuHandler={this.menuHandler} />
{this.state.respondMenu?
<ResponsiveNav
places={this.props.places}
menuHandler={this.menuHandler}/>:
null}
</div>);
}
componentWillUnmount(){
window.removeEventListener('resize', this.updateWidth);
}
}
/*
APP CONTAINER TOP-LEVEL PARENT
*/
class AppContainer extends React.Component{
constructor(props){
super(props);
this.state={
code: DEFAULT_TEXT
}
this.handleClear=this.handleClear.bind(this);
this.handleReset=this.handleReset.bind(this);
this.handleCode=this.handleCode.bind(this);
}
handleClear(e){
e.preventDefault();
this.setState({code: ''});
}
handleReset(e){
e.preventDefault();
this.setState({code: DEFAULT_TEXT});
}
handleCode(e){
this.setState({code: e.target.value})
}
render(){
return(<div>
<Navbar places={{'Reset':this.handleReset,'Clear':this.handleClear}}/>
<div className='mainContent'>
<CodeBox value={this.state.code} handleCode={this.handleCode}/>
<DomBox text={this.state.code}/>
</div>
</div>);
}
}
/*
CODE BOX: UI ENTRY OF MARKUP INTO TEXTAREA
PROPS: {value: (''), handleCode: FUNCTION FOR onChange EVENT}
*/
class CodeBox extends React.Component{
constructor(props){
super(props);
}
render(){
return(<textarea
id='editor'
className='codeBox uiBox'
value={this.props.value}
onChange={this.props.handleCode}></textarea>)
}
}
CodeBox.propTypes={
value: PropTypes.string,
handleCode: PropTypes.func
}
/*
DOM BOX: RETURNS DOM RENDERED MARKUP
PROPS: {text: UNALTERED STRING OF MARKUP}
.replace(/(\r\n|\r|\n)/g,"<br/>")
*/
class DomBox extends React.Component{
constructor(props){
super(props);
}
createMarkUp(m){
return {__html:marked(m,{renderer:MarkUp})};
}
render(){
return(<div id='preview' className='domBox uiBox' dangerouslySetInnerHTML={this.createMarkUp(this.props.text)}></div>)
}
}
DomBox.propTypes={
text: PropTypes.string
}
render(<AppContainer />, document.getElementById('rootContainer'));
View Compiled