Skip to content

Commit

Permalink
feat(MainSiteArticleBody): added MainSiteArticleBody component (#201)
Browse files Browse the repository at this point in the history
* initial article

* finished body

* update legacy mdx file

* refactor CSS global
  • Loading branch information
zeehang authored Jul 27, 2019
1 parent c6cbea7 commit 5226c07
Show file tree
Hide file tree
Showing 5 changed files with 245 additions and 0 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
"react-emotion": "^9.2.12",
"react-helmet": "^5.2.0",
"react-plyr": "^2.1.1",
"react-string-replace": "0.4.4",
"slugify": "^1.3.3",
"typescript": "3.4.4",
"webfontloader": "^1.6.28"
Expand Down
69 changes: 69 additions & 0 deletions src/components/MainSiteArticleBody/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
name: Main Site Article Body
route: /main-site-article-body
---

import { Playground, Props } from 'docz'
import MainSiteArticleBody from '.'
import MainSiteImage from '../MainSiteImage'
import { css } from 'react-emotion'

# Main Site Article Body

How an article displays on the main site

<Props of={MainSiteArticleBody} />

## Internal components
Internal images must follow the props given by `MainSiteImage`
<Props of={MainSiteImage} />


## Example usage
<Playground>
<MainSiteArticleBody
isLegacy={false}
content={
[
{
type: 'text',
value: {
isHTML: false,
value: 'Former UCLA doctor James Heaps is facing a growing number of civil suits for alleged sexual abuse.'
}
},
{
type: 'text',
value: {
isHTML: false,
value: 'Two more civil lawsuits from nine women alleging sexual abuse by Heaps were filed Tuesday, according to a press release from Manly, Stewart & Finaldi, the law firm representing the women. This brings the total number of civil suits against Heaps up to at least five. Three of the nine women were UCLA students at the time of the alleged incidents, according to court documents.'
}
},
{
type: 'text',
value: {
isHTML: false,
value: 'Heaps worked at the Ronald Reagan UCLA Medical Center from 2014 to 2018 as an obstetrician-gynecologist and held medical staff privileges there for about 30 years. Prior to his employment at the medical center, he worked at what is now the UCLA Arthur Ashe Student Health and Wellness Center as a part-time doctor from 1983 to 2010.'
}
},
{
type: 'image',
value: {
imageURL: 'https://dailybruin.com/images/2018/06/web.sp_.kellihayes.KH_.1-640x426.jpg',
imageCaption: 'Anna Tsai, a first-year physics student, designed "The Garden of Eden" for the 18th Fashion and Student Trends runway show, which took place Thursday night in Pauley Pavilion.',
imageCredit: 'Joe Bruin',
imageStaffPosition: 'Daily Bruin senior staff',
imageCreditProfileURL: 'https://google.com'
}
},
{
type: 'text',
value: {
isHTML: true,
value: '\n<p>Additionally, the city approved an NWWNC-endorsed bid&nbsp;<a href=\"https:\/\/dailybruin.com\/2018\/04\/24\/broxton-avenue-proposed-to-turn-into-pedestrian-only-area-for-events\/\" target=\"_blank\" rel=\"noreferrer noopener\">to transform the south side of Broxton Avenue into a pedestrian plaza<\/a>, which would permanently close the area off to traffic and reserve it for people and events, Skiles said.<\/p>\n'
}
}
]
}
/>
</Playground>
161 changes: 161 additions & 0 deletions src/components/MainSiteArticleBody/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import * as React from 'react'
import { css } from 'react-emotion'
import reactStringReplace from 'react-string-replace'
// tslint:disable-next-line:no-submodule-imports
import { renderToStaticMarkup } from 'react-dom/server'
import MainSiteLink from '../MainSiteLink'
import MainSiteImage, { MainSiteImageProps } from '../MainSiteImage'
import {
bodyTextSize,
bodyFont,
bodyTextCSS,
} from '../../globals/mainsiteGlobalStyles'

enum ContentType {
Text = 'text',
Image = 'image',
Line = 'line',
Video = 'video',
Break = 'break',
}

interface Content {
type: ContentType
/** This takes in a JSON object with the appropriate props */
value?: any
}

/**
* Properties required for a main site article
*/
export interface MainSiteArticleBodyProps {
/** Determines whether this is pre Gutenberg Block wordpress (< 5.0) */
isLegacy: boolean
/** Array of content to be rendered */
content: Content[]
/** Legacy content string */
legacyContent?: string
}

interface MainSiteText {
/** Whether this should be rendered as HTML or in a p tag */
isHTML: boolean
value: string
}

const bodySizeCSS = css`
margin-left: auto;
margin-right: auto;
max-width: 620px;
padding: 1rem;
`

class MainSiteArticleBody extends React.Component<MainSiteArticleBodyProps> {
public render() {
/** Check and render legacy content */
if (this.props.isLegacy) {
return (
<article
className={css`
${bodySizeCSS};
${bodyTextCSS};
`}
dangerouslySetInnerHTML={{
__html: this.props.legacyContent,
}}
/>
)
}

const renderedContent = this.props.content.map(
(content: any, i: number) => {
switch (content.type) {
case ContentType.Text:
const text = content.value as MainSiteText
if (!text.isHTML) {
return (
<p
key={i}
className={css`
${bodyTextCSS};
`}
>
{text.value}
</p>
)
} else {
/** Replace all links with a MainSiteLink */
/**
* We render the links as MainSiteLinks in a string
* and use react-string-replace to help with the final output
*/
const replacedText = reactStringReplace(
text.value,
/<\s*a[^>] *(.*?)<\s*\/\s*a>/g,
(match, num: number) => {
// first we find the link text and URL
const linkURLStart: number = match.indexOf('href="') + 6
const linkURLEnd: number = match.indexOf(
'"',
linkURLStart + 1
)
const linkURLString: string = match.substring(
linkURLStart,
linkURLEnd
)

// next we find the link text
const textStart: number = match.indexOf('>', linkURLEnd) + 1
const textString: string = match.substring(textStart)

// render this as a MainSiteLink in static markup
return renderToStaticMarkup(
<MainSiteLink key={num} href={linkURLString}>
{textString}
</MainSiteLink>
)
}
)

// remove outer <p> tags
const stringText = replacedText.join('')
const firstTag = stringText.indexOf('<p>')
const finalTag = stringText.lastIndexOf('</p>')
const finalRender = stringText.substring(firstTag + 3, finalTag)

return (
<p
key={i}
className={css`
${bodyTextCSS};
`}
dangerouslySetInnerHTML={{
__html: finalRender,
}}
/>
)
}
case ContentType.Image:
const image = content.value as MainSiteImageProps
return <MainSiteImage key={i} {...image} />
case ContentType.Line:
return <hr />
case ContentType.Break:
return <br />
}
}
)

return (
<article
className={css`
${bodySizeCSS};
`}
>
{renderedContent}
</article>
)
}
}

export default MainSiteArticleBody
8 changes: 8 additions & 0 deletions src/globals/mainsiteGlobalStyles.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { css } from 'react-emotion'

/** Web fonts loaded here - only in a browser */
if (typeof window !== 'undefined') {
// tslint:disable-next-line:no-var-requires
Expand Down Expand Up @@ -51,3 +53,9 @@ export const bodyLineHeight = '1.45em'
/** CSS breakpoints */
export const mediaMobileBreakpoint = '@media (max-width: 600px)'
export const secheadMobileBreakpoint = '@sechead (max-width: 600px)'

/** Combined themes */
export const bodyTextCSS = css`
font-size: ${bodyTextSize};
font-family: ${bodyFont};
`
6 changes: 6 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -13587,6 +13587,12 @@ react-simple-code-editor@^0.9.0:
version "0.9.10"
resolved "https://registry.yarnpkg.com/react-simple-code-editor/-/react-simple-code-editor-0.9.10.tgz#1ab5ea7215687ed918c6d0dae90736cf01890905"

[email protected]:
version "0.4.4"
resolved "https://registry.yarnpkg.com/react-string-replace/-/react-string-replace-0.4.4.tgz#24006fbe0db573d5be583133df38b1a735cb4225"
dependencies:
lodash "^4.17.4"

[email protected]:
version "5.4.4"
resolved "https://registry.yarnpkg.com/react-testing-library/-/react-testing-library-5.4.4.tgz#3fa787999492be94b228e4540a7211556bf4fd94"
Expand Down

0 comments on commit 5226c07

Please sign in to comment.