- generate hash string
- truncate
- remove duplicates from array of primitives
- fetch sequentially
- fetch all
- throttling
- fetch get status
- sr only
- scroll to el
- scroll snap
- lazy loading images
- detect mobile
- react clone children
- netlify redirect
- conventional commits
- tag GH version
- delete GH tag
- publish beta
- list global dependencies
- grant write permission to all users
const genHash = (
length,
string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-',
) => {
let i = 0
let hash = ''
while (i < length) {
hash += string.charAt(Math.floor(Math.random()*string.length))
i++
}
return hash
}
function truncate({ text, chars = 100, clean = true, ellipses = false }) {
const over = text.length > chars
const a = text.substring(0, chars)
const end = clean ? a.lastIndexOf(' ') : a.length
const b = over ? a.substring(0, end) : text
const e = over && ellipses ? '...' : ''
return `${b}${e}`
}
[... new Set(arr)]
function getResources(urls){
let targetURL = urls.shift()
if (targetURL){
fetch(targetURL)
.then(res => {
// loaded
})
.catch(() => {
// failed
})
.finally(() => {
getResources(urls)
})
}
}
Promise.all(urls.map(url => fetch(url)))
.then(res => {
// all loaded
console.log('load')
}, () => {
console.log('failed')
// one or more failed
})
let scrollCache = undefined
window.addEventListener('scroll', e => {
if (!cached) {
setTimeout(() => {
scrollCache = undefined
}, 100)
}
scrollCache = e
})
fetch(url)
.then(r => r.json().then(d => ({status: r.status, body: d})))
.sr-only {
border: 0 !important;
clip: rect(1px, 1px, 1px, 1px) !important;
-webkit-clip-path: inset(50%) !important;
clip-path: inset(50%) !important;
height: 1px !important;
margin: -1px !important;
overflow: hidden !important;
padding: 0 !important;
position: absolute !important;
width: 1px !important;
white-space: nowrap !important;
}
/* show on focus */
.sr-only-focusable:focus,
.sr-only-focusable:active {
clip: auto !important;
-webkit-clip-path: none !important;
clip-path: none !important;
height: auto !important;
margin: auto !important;
overflow: visible !important;
width: auto !important;
white-space: normal !important;
}
function scrollTo(el, offset = 0) {
const top = el.getBoundingClientRect().top + offset
const scrollTop = window.pageYOffset || document.documentElement.scrollTop
const destY = scrollTop + top
window.scrollTo(0, destY)
}
horizontal gallery
<style>
#gallery {
scroll-snap-type: x mandatory;
overflow-x: scroll;
display: flex;
}
#gallery img {
scroll-snap-align: center;
}
</style>
<div id="gallery">
<img src="cat.jpg">
<img src="dog.jpg">
<img src="another_cute_animal.jpg">
</div>
journeyed product page
<style>
article {
scroll-snap-type: y proximity;
/* pad for header */
scroll-padding-top: 15vh;
overflow-y: scroll;
}
section {
scroll-snap-align: start;
}
header {
position: fixed;
height: 10vh;
}
</style>
<article>
<header> Header </header>
<section> Section One </section>
<section> Section Two </section>
<section> Section Three </section>
</article>
const lazyLoad = target => {
const io = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target
const src = img.getAttribute('data-lazy')
img.setAttribute('src', src)
img.classList.add('fade')
observer.disconnect()
}
})
})
io.observe(target)
}
document.querySelectorAll('img').forEach(lazyLoad)
const isMobile = {
android: () => navigator.userAgent.match(/Android/i),
blackberry: () => navigator.userAgent.match(/BlackBerry/i),
ios: () => navigator.userAgent.match(/iPhone|iPad|iPod/i),
opera: () => navigator.userAgent.match(/Opera Mini/i),
windows: () => navigator.userAgent.match(/IEMobile/i),
any: () => (
isMobile.android() ||
isMobile.blackberry() ||
isMobile.ios() ||
isMobile.opera() ||
isMobile.windows()
),
}
React.Children.map(children, child => {
return React.cloneElement(child, {
someProp: someVal
})
})
create a _redirects
file in your build folder to redirect back home regardless of the requested URL
/* /index.html 200
alternatively, change your build script to do this for you
"build": "react-scripts build && echo '/* /index.html 200' > build/_redirects"
squash feature branches with master using conventional commit messages and semantic versioning
<type>: <description>
[optional body]
[optional footer (eg. 'Fixes #13')]
types:
- build: changes to build system/dependencies
- docs: doc changes
- feat: new feature
- fix: bug fix
- perf: change implemented to improve performance
- refactor: change of code structure
- style: white-space/formatting
- test: add/change tests
fix -> patch release (0.0.X) feat -> minor release (0.X.0) any breaking change regardless of type -> major release (X.0.0)
$ git tag 0.1.0 && git push --tags
add title and desc on GH at https://github.com/shwilliam/<PACKAGE_NAME>/releases/new
$ git tag -d 0.1.0 && git push origin :refs/tags/0.1.0
in package.json add version suffix -beta.0
(increment beta version as necessary)
npm publish --tag beta
(now available with npm i <PACKAGE_NAME>@beta
)
npm list -g --depth 0
sudo chmod [-R] 777 [dir]