Skip to content

Commit

Permalink
feat: use mql as fetcher (#162)
Browse files Browse the repository at this point in the history
* build: use mql as fetcher

* refactor: access methods directly

* build: tiny badge

* fix: dependency in the right place

* build: tweaks

* build: remove size-limit

* fix: vanilla bundle

* fix: revert modulesOnly

* build: mql as global dependency

* build: add minify version

* build: tweaks
  • Loading branch information
Kikobeats committed Oct 14, 2019
1 parent 4fd1609 commit b7eac46
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 180 deletions.
14 changes: 4 additions & 10 deletions packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"previsualization"
],
"dependencies": {
"@microlink/mql": "~0.5.5",
"nanoclamp": "~1.2.11"
},
"devDependencies": {
Expand All @@ -31,7 +32,6 @@
"@babel/plugin-transform-react-inline-elements": "latest",
"@babel/preset-env": "latest",
"@babel/preset-react": "latest",
"@size-limit/preset-small-lib": "latest",
"@storybook/addon-a11y": "latest",
"@storybook/addon-storyshots": "latest",
"@storybook/react": "latest",
Expand Down Expand Up @@ -76,9 +76,7 @@
"dev": "start-storybook -p 6006",
"format": "prettier-standard index.js {src,stories,.storybook}/**/*.js --single-quote",
"lint": "standard",
"posttest": "npm run size",
"pretest": "npm run lint",
"size": "npm run build && size-limit",
"start": "node scripts/start.js",
"test": "jest --detectOpenHandles"
},
Expand All @@ -98,12 +96,6 @@
"publishConfig": {
"access": "public"
},
"size-limit": [
{
"path": "./dist/microlink.min.js",
"limit": "10 kB"
}
],
"standard": {
"globals": [
"fetch"
Expand All @@ -117,5 +109,7 @@
"plugins": [
"jsx-a11y"
]
}
},
"umd:main": "dist/microlink.js",
"unpkg": "dist/microlink.js"
}
116 changes: 52 additions & 64 deletions packages/react/rollup.config.js
Original file line number Diff line number Diff line change
@@ -1,92 +1,80 @@
import nodeResolve from 'rollup-plugin-node-resolve'
import visualizer from 'rollup-plugin-visualizer'
import { terser } from 'rollup-plugin-terser'
import filesize from 'rollup-plugin-filesize'
import { terser } from 'rollup-plugin-terser'
import commonjs from 'rollup-plugin-commonjs'
import replace from 'rollup-plugin-replace'

import babel from 'rollup-plugin-babel'
import fs from 'fs'

const babelRc = JSON.parse(fs.readFileSync('./.babelrc'))

const cjs = {
exports: 'named',
format: 'cjs',
sourcemap: true
}

const esm = {
format: 'esm',
sourcemap: true
const globals = {
react: 'React',
'react-dom': 'ReactDOM',
'styled-components': 'styled',
'@microlink/mql': 'mql'
}

const getCJS = override => ({ ...cjs, ...override })
const getESM = override => ({ ...esm, ...override })

const commonPlugins = [
const plugins = ({ compress = false }) => [
nodeResolve(),
babel({
babelrc: false,
externalHelpers: false,
...babelRc
}),
commonjs(),
filesize()
compress && terser({ sourcemap: true }),
filesize(),
visualizer({ template: 'treemap' }),
replace({
'process.env.NODE_ENV': JSON.stringify('production')
})
]

const configBase = {
input: './src/index.js',
// \0 is rollup convention for generated in memory modules
external: id =>
!id.startsWith('\0') && !id.startsWith('.') && !id.startsWith('/'),
plugins: commonPlugins
}

const globals = {
react: 'React',
'react-dom': 'ReactDOM',
'styled-components': 'styled'
}

const standaloneBaseConfig = {
...configBase,
const build = ({ file, format, name, exports }) => ({
input: './src/index.js',
output: {
file: 'dist/microlink.js',
format: 'umd',
exports: 'named',
globals,
name: 'microlink',
sourcemap: true
file,
format,
exports,
name,
globals
},
external: Object.keys(globals)
}
external: Object.keys(globals),
plugins: plugins({ compress: file.includes('.min.') })
})

const prodPlugins = [
replace({
'process.env.NODE_ENV': JSON.stringify('production')
export default [
build({
format: 'umd',
file: 'dist/microlink.js',
name: 'microlink'
}),
build({
format: 'umd',
file: 'dist/microlink.min.js',
name: 'microlink'
}),
terser({
sourcemap: true
build({
format: 'esm',
file: 'dist/microlink.m.js',
exports: 'named'
}),
visualizer({ template: 'treemap' })
build({
format: 'esm',
file: 'dist/microlink.m.min.js',
exports: 'named'
}),
build({
format: 'cjs',
file: 'dist/microlink.cjs.js',
exports: 'named'
}),
build({
format: 'cjs',
file: 'dist/microlink.cjs.min.js',
exports: 'named'
})
]

const standaloneProdConfig = {
...standaloneBaseConfig,
output: {
...standaloneBaseConfig.output,
file: 'dist/microlink.min.js'
},
plugins: standaloneBaseConfig.plugins.concat(prodPlugins)
}

const serverConfig = {
...configBase,
output: [
getESM({ file: 'dist/microlink.m.js' }),
getCJS({ file: 'dist/microlink.cjs.js' })
]
}

export default [standaloneProdConfig, serverConfig]
30 changes: 11 additions & 19 deletions packages/react/src/components/Card/CardContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@ import CardText from './CardText'
import { media, isLarge, isSmall, isNil } from '../../utils'

const REGEX_STRIP_WWW = /^www\./
const BADGE_WIDTH = '16px'
const BADGE_HEIGHT = '12px'

const getHostname = href => {
if (isNil(href)) {
return ''
}

if (isNil(href)) return ''
const { hostname } = new URL(href)
return hostname.replace(REGEX_STRIP_WWW, '')
}
Expand Down Expand Up @@ -79,35 +78,28 @@ const Footer = styled('footer')`
`};
`

const PoweredByBadge = styled('span').attrs({ title: 'microlink.io' })`
const PoweredBy = styled('span').attrs({ title: 'microlink.io' })`
background: url('https://cdn.microlink.io/logo/logo.svg') no-repeat center
center;
display: block;
margin-left: 14px;
margin-left: 15px;
transition: filter 0.15s ease, opacity 0.15s ease;
&:not(:hover) {
filter: grayscale(100%);
opacity: 0.75;
}
${({ cardSize }) => {
const badgeWidth = !isSmall(cardSize) ? '22px' : '18px'
const badgeHeight = !isSmall(cardSize) ? '16px' : '13px'
return css`
min-width: ${badgeWidth};
width: ${badgeWidth};
background-size: ${badgeWidth};
height: ${badgeHeight};
`
}}
min-width: ${BADGE_WIDTH};
width: ${BADGE_WIDTH};
background-size: ${BADGE_WIDTH};
height: ${BADGE_HEIGHT};
`

export default ({ title, description, url, cardSize, className }) => {
const isSmallCard = isSmall(cardSize)
const formattedUrl = useMemo(() => getHostname(url), [url])
const onPoweredByClick = useCallback(e => {
const handleOnClick = useCallback(e => {
e.preventDefault()
window.open('https://www.microlink.io', '_blank')
})
Expand All @@ -127,7 +119,7 @@ export default ({ title, description, url, cardSize, className }) => {
)}
<Footer cardSize={cardSize} className='microlink_card__content_url'>
<CardText useNanoClamp={false}>{formattedUrl}</CardText>
<PoweredByBadge cardSize={cardSize} onClick={onPoweredByClick} />
<PoweredBy onClick={handleOnClick} />
</Footer>
</Content>
)
Expand Down
16 changes: 7 additions & 9 deletions packages/react/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ import PropTypes from 'prop-types'
import { CardWrap, CardMedia, CardContent, CardEmpty } from './components/Card'

import {
defaultApiParameters,
isNil,
createApiUrl,
fetchFromApiUrl,
getApiUrl,
fetchFromApi,
getUrlPath,
imageProxy,
someProp,
Expand Down Expand Up @@ -51,7 +50,7 @@ function Microlink (props) {
isLoadingUndefined ? true : loadingProp
)
const [cardData, setCardData] = useState({})
const apiUrl = useMemo(() => createApiUrl(props), [props])
const [apiUrl, apiUrlProps] = useMemo(() => getApiUrl(props), [props])

const isLazyEnabled = useMemo(
() => isLazySupported && (lazy === true || isObject(lazy)),
Expand All @@ -73,11 +72,11 @@ function Microlink (props) {
setLoading(true)
const fetch = isFunction(setData)
? Promise.resolve({})
: fetchFromApiUrl(apiUrl, props.apiKey)
: fetchFromApi(props.url, apiUrl, apiUrlProps)

fetch.then(({ data }) => mergeData(data))
}
}, [apiUrl, canFetchData, setData, props.apiKey])
}, [apiUrl, canFetchData, setData, apiUrlProps.headers['x-api-key']])

const mergeData = useCallback(
fetchData => {
Expand Down Expand Up @@ -179,8 +178,7 @@ Microlink.defaultProps = {
media: ['image', 'logo'],
muted: true,
playsInline: true,
size: 'normal',
...defaultApiParameters
size: 'normal'
}

Microlink.propTypes = {
Expand All @@ -202,6 +200,6 @@ Microlink.propTypes = {
url: PropTypes.string
}

export { imageProxy, createApiUrl, fetchFromApiUrl }
export { imageProxy, getApiUrl, fetchFromApi }

export default Microlink
65 changes: 20 additions & 45 deletions packages/react/src/utils/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* global fetch */

import { css } from 'styled-components'
import { fetchFromApi, getApiUrl as createApiUrl } from '@microlink/mql'

const REGEX_HTTPS = /^https/
const REGEX_LOCALHOST = /http:\/\/localhost/
Expand Down Expand Up @@ -31,56 +30,32 @@ export const media = {
`
}

const apiValue = (key, value) => (value === true ? `${key}` : `${key}=${value}`)

export const defaultApiParameters = {
contrast: false,
prerender: 'auto',
screenshot: false,
video: false
}

export const createApiUrl = props => {
const { apiKey, url: targetUrl, prerender, contrast, media } = props
const takeScreenshot = media.includes('screenshot')
const hasVideo = media.includes('video')

const alias = apiKey ? 'pro' : 'api'
let url = `https://${alias}.microlink.io/?url=${encodeURIComponent(
targetUrl
)}`

if (hasVideo) {
url = `${url}&${apiValue('video', hasVideo)}`
}

if (!isNil(contrast) && contrast !== defaultApiParameters.contrast) {
url = `${url}&${apiValue('palette', contrast)}`
}

if (!isNil(prerender) && prerender !== defaultApiParameters.prerender) {
url = `${url}&${apiValue('prerender', prerender)}`
}

if (takeScreenshot) {
url = `${url}&${apiValue('screenshot', takeScreenshot)}`
}

return url
}

export const fetchFromApiUrl = (apiUrl, apiKey) => {
const headers = apiKey ? { 'x-api-key': apiKey } : {}
return fetch(apiUrl, { headers }).then(res => res.json())
}
export const getApiUrl = ({
apiKey,
url,
prerender = 'auto',
contrast = false,
media,
...opts
}) =>
createApiUrl(url, {
apiKey,
video: media.includes('video'),
screenshot: media.includes('screenshot'),
palette: contrast,
prerender,
...opts
})

export { fetchFromApi }

export const isLarge = cardSize => cardSize === 'large'

export const isSmall = cardSize => cardSize === 'small'

export const imageProxy = url => {
if (!url || REGEX_LOCALHOST.test(url) || REGEX_HTTPS.test(url)) return url
return `https://images.weserv.nl/?url=${encodeURIComponent(url).replace(
return `https://images.weserv.nl/?url=${encodeURI(url).replace(
'http://',
''
)}`
Expand Down
Loading

0 comments on commit b7eac46

Please sign in to comment.