Skip to content

Commit

Permalink
feat: added new tools
Browse files Browse the repository at this point in the history
  • Loading branch information
Uninen committed Nov 30, 2024
1 parent 44be7ba commit 550dcfc
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 6 deletions.
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## 0.5.0 (2024-12-01)

- Feat: added new tools: `isValidSecureUrl`, `prefetchImages`, `browserIsIE`, `browserIsSupported` and `isString` type helper.
- Fix: added checks for running in SSR mode.

## 0.4.1 (2024-11-27)

- Chore: typec-check in CI.
Expand Down
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@ General utilities for Web development

### Browser

- `copyToClipboard(content: string): boolean`
- `getCookie(name: string): string | null`
- `storageAvailable(type: 'localStorage' | 'sessionStorage'): boolean`
- `browserIsIE()`
- `copyToClipboard(content: string)`
- `getCookie(name: string)`
- `isValidSecureUrl(url: string)`
- `prefetchImages(url: string|string[])`
- `storageAvailable(type: 'localStorage' | 'sessionStorage')`

### Vue

- `getNextPath(router?: Router): string` - returns the value of `?next` query param or `/`
- `getNextPath(router?: Router)` - returns the value of `?next` query param or `/`
- `isString(value: string | LocationQueryValue[])`

## Installation

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@slipmatio/toolbelt",
"type": "module",
"version": "0.4.1",
"version": "0.5.0",
"main": "dist/toolbelt.js",
"module": "dist/toolbelt.js",
"exports": {
Expand Down
102 changes: 101 additions & 1 deletion src/browser.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,31 @@
export function isSSR() {
try {
return typeof window === 'undefined' && typeof document === 'undefined'
} catch {
return true
}
}

export function hasTimeZoneSupport() {
if (isSSR()) {
return false
}
try {
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone
return Boolean(tz)
} catch {
return false
}
}

/**
* Checks whether the given Storage is available and usable.
*/
export function storageAvailable(type: 'localStorage' | 'sessionStorage'): boolean {
export function storageAvailable(type: 'localStorage' | 'sessionStorage') {
if (isSSR()) {
return false
}

let storage: Storage
if (type === 'localStorage') {
storage = window.localStorage
Expand Down Expand Up @@ -36,6 +60,9 @@ export function storageAvailable(type: 'localStorage' | 'sessionStorage'): boole
* Returns the cookie as a string or null if not found.
*/
export function getCookie(name: string) {
if (isSSR()) {
return null
}
let cookieValue = ''
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';')
Expand All @@ -60,6 +87,9 @@ export function getCookie(name: string) {
* Simple clipboard copy for modern browsers. Returns true if successful.
*/
export function copyToClipboard(content: string) {
if (isSSR()) {
return false
}
const d = document
try {
const el = document.createElement('input')
Expand All @@ -74,3 +104,73 @@ export function copyToClipboard(content: string) {
return false
}
}

/**
* Basic URL validation that checks if string can be parsed as URL
* Input must start with https://
*/
export function isValidSecureUrl(url: string) {
if (!url?.trim()) {
return false
}

try {
const parsed = new URL(url)
return parsed.protocol === 'https:'
} catch {
return false
}
}

/**
* Simple helper to prefetch images
* @param urls URL or array of URLs to prefetch
*/
export async function prefetchImages(urls: string | string[]) {
if (isSSR()) {
return []
}

const urlList = Array.isArray(urls) ? urls : [urls]

return Promise.all(
urlList.map(
(url) =>
new Promise<{ url: string; success: boolean }>((resolve) => {
const img = new Image()

function cleanup() {
img.onload = null
img.onerror = null
}

img.onload = () => {
cleanup()
resolve({ url, success: true })
}

img.onerror = () => {
cleanup()
resolve({ url, success: false })
}

img.src = url
})
)
)
}

export function browserIsIE() {
if (isSSR()) {
return false
}
const ua = window.navigator.userAgent
return ua.indexOf('MSIE ') > -1 || ua.indexOf('Trident/') > -1
}

export function browserIsSupported() {
if (isSSR()) {
return false
}
return !browserIsIE() && hasTimeZoneSupport() && storageAvailable('localStorage')
}
2 changes: 2 additions & 0 deletions src/vue/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ export function getNextPath(router?: Router): string {
}
return next
}

export { isString }

0 comments on commit 550dcfc

Please sign in to comment.