kopia lustrzana https://dev.funkwhale.audio/funkwhale/funkwhale
fix(front): ensure compatibility with 94% of browsers in the wild #2501
rodzic
351db1fd5b
commit
7ff624b51b
|
@ -0,0 +1,24 @@
|
||||||
|
# Browser support targeting 95% coverage while enabling modern features
|
||||||
|
# This targets browsers that support ES2020+ and modern CSS features
|
||||||
|
|
||||||
|
# Cover 95% of global usage
|
||||||
|
> 1%
|
||||||
|
last 2 versions
|
||||||
|
not dead
|
||||||
|
|
||||||
|
# Exclude problematic browsers
|
||||||
|
not ie 11
|
||||||
|
not op_mini all
|
||||||
|
not android <= 4.4
|
||||||
|
not samsung <= 4
|
||||||
|
|
||||||
|
# Ensure modern browser support for ES2020+ features
|
||||||
|
chrome >= 87
|
||||||
|
firefox >= 78
|
||||||
|
safari >= 14
|
||||||
|
edge >= 88
|
||||||
|
|
||||||
|
# Mobile browsers
|
||||||
|
ios >= 14
|
||||||
|
and_chr >= 87
|
||||||
|
and_ff >= 78
|
|
@ -100,6 +100,7 @@
|
||||||
"@vue/eslint-config-typescript": "12.0.0",
|
"@vue/eslint-config-typescript": "12.0.0",
|
||||||
"@vue/test-utils": "2.4.1",
|
"@vue/test-utils": "2.4.1",
|
||||||
"@vue/tsconfig": "0.6.0",
|
"@vue/tsconfig": "0.6.0",
|
||||||
|
"autoprefixer": "10.4.21",
|
||||||
"cypress": "13.6.4",
|
"cypress": "13.6.4",
|
||||||
"eslint": "8.57.0",
|
"eslint": "8.57.0",
|
||||||
"eslint-config-standard": "17.1.0",
|
"eslint-config-standard": "17.1.0",
|
||||||
|
@ -115,6 +116,7 @@
|
||||||
"msw-auto-mock": "0.18.0",
|
"msw-auto-mock": "0.18.0",
|
||||||
"openapi-typescript": "7.6.0",
|
"openapi-typescript": "7.6.0",
|
||||||
"patch-package": "8.0.0",
|
"patch-package": "8.0.0",
|
||||||
|
"postcss": "8.5.6",
|
||||||
"rollup-plugin-visualizer": "5.9.0",
|
"rollup-plugin-visualizer": "5.9.0",
|
||||||
"sass": "1.68.0",
|
"sass": "1.68.0",
|
||||||
"sinon": "15.0.2",
|
"sinon": "15.0.2",
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
export default {
|
||||||
|
plugins: {
|
||||||
|
autoprefixer: {
|
||||||
|
overrideBrowserslist: [
|
||||||
|
'> 1%',
|
||||||
|
'last 2 versions',
|
||||||
|
'not dead',
|
||||||
|
'not ie 11',
|
||||||
|
'not op_mini all',
|
||||||
|
'chrome >= 87',
|
||||||
|
'firefox >= 78',
|
||||||
|
'safari >= 14',
|
||||||
|
'edge >= 88',
|
||||||
|
'ios >= 14'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,19 +3,9 @@ export interface Token {
|
||||||
value: string
|
value: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Normalizes a query string by splitting it into tokens while respecting quoted phrases.
|
|
||||||
*
|
|
||||||
* @param query - The input query string to normalize
|
|
||||||
* @returns Array of normalized tokens with quoted phrases preserved as single tokens
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* ```
|
|
||||||
* normalizeQuery('this is "my query" go')
|
|
||||||
* // Returns: ['this', 'is', 'my query', 'go']
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
export function normalizeQuery (query: string): string[] {
|
export function normalizeQuery (query: string): string[] {
|
||||||
|
// given a string such as 'this is "my query" go', returns
|
||||||
|
// an array of tokens like this: ['this', 'is', 'my query', 'go']
|
||||||
if (!query) return []
|
if (!query) return []
|
||||||
|
|
||||||
const match = query.match(/\\?.|^$/g)
|
const match = query.match(/\\?.|^$/g)
|
||||||
|
@ -42,46 +32,51 @@ const unquote = (str: string) => {
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
const quoteIfNecessary = (str: string) =>
|
export function parseTokens (normalizedQuery: string[]): Token[] {
|
||||||
str.includes(' ')
|
// given an array of tokens as returned by normalizeQuery,
|
||||||
? `"${str}"`
|
// returns a list of objects such as [
|
||||||
: str
|
// {
|
||||||
|
// field: 'status',
|
||||||
/**
|
// value: 'pending'
|
||||||
* Parses an array of normalized query tokens into structured Token objects.
|
// },
|
||||||
*
|
// {
|
||||||
* @param normalizedQuery - Array of tokens as returned by normalizeQuery
|
// field: null,
|
||||||
* @returns Array of Token objects with field and value properties
|
// value: 'hello'
|
||||||
*
|
// }
|
||||||
* @example
|
// ]
|
||||||
* ```
|
return normalizedQuery.map(t => {
|
||||||
* parseTokens(['status:pending', 'hello'])
|
// we split the token on ":"
|
||||||
* // Returns:
|
|
||||||
* // [
|
|
||||||
* // { field: 'status', value: 'pending' },
|
|
||||||
* // { field: null, value: 'hello' }
|
|
||||||
* // ]
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
export const parseTokens = (normalizedQuery: string[]): Token[] =>
|
|
||||||
normalizedQuery.map(t => {
|
|
||||||
// Split the token on ":" to separate field from value
|
|
||||||
const parts = t.split(/:(.+)/)
|
const parts = t.split(/:(.+)/)
|
||||||
return parts.length === 1
|
if (parts.length === 1) {
|
||||||
? { field: null, value: t } // No field specified
|
// no field specified
|
||||||
: { field: parts[0], value: unquote(parts[1]) } // Field:value format, remove quotes
|
return { field: null, value: t }
|
||||||
|
}
|
||||||
|
|
||||||
|
// first item is the field, second is the value, possibly quoted
|
||||||
|
const [field, value] = parts
|
||||||
|
|
||||||
|
// we remove surrounding quotes if any
|
||||||
|
return { field, value: unquote(value) }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function compileTokens (tokens: Token[]) {
|
||||||
|
// given a list of tokens as returned by parseTokens,
|
||||||
|
// returns a string query
|
||||||
|
const parts = tokens.map(token => {
|
||||||
|
const { field } = token
|
||||||
|
let { value } = token
|
||||||
|
|
||||||
|
if (value.includes(' ')) {
|
||||||
|
value = `"${value}"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if (field) {
|
||||||
|
return `${field}:${value}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return value
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
return parts.join(' ')
|
||||||
* Compiles an array of Token objects back into a query string.
|
}
|
||||||
*
|
|
||||||
* @param tokens - Array of Token objects as returned by parseTokens
|
|
||||||
* @returns A formatted query string
|
|
||||||
*/
|
|
||||||
export const compileTokens = (tokens: Token[]) =>
|
|
||||||
tokens.map(({field, value}) =>{
|
|
||||||
field
|
|
||||||
? `${field}:${quoteIfNecessary(value)}`
|
|
||||||
: quoteIfNecessary(value)
|
|
||||||
})
|
|
||||||
.join(' ')
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
"lib": ["ES2023", "DOM", "DOM.Iterable"],
|
||||||
"typeRoots": ["node_modules", "node_modules/@types"],
|
"typeRoots": ["node_modules", "node_modules/@types"],
|
||||||
"types": [
|
"types": [
|
||||||
"vitest/globals",
|
"vitest/globals",
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { VitePWA } from 'vite-plugin-pwa'
|
||||||
import { fileURLToPath, URL } from 'node:url'
|
import { fileURLToPath, URL } from 'node:url'
|
||||||
import UnoCSS from 'unocss/vite'
|
import UnoCSS from 'unocss/vite'
|
||||||
|
|
||||||
|
|
||||||
import manifest from './pwa-manifest.json'
|
import manifest from './pwa-manifest.json'
|
||||||
|
|
||||||
import VueI18n from '@intlify/unplugin-vue-i18n/vite'
|
import VueI18n from '@intlify/unplugin-vue-i18n/vite'
|
||||||
|
@ -93,7 +94,14 @@ export default defineConfig(({ mode }) => ({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
esbuild: {
|
||||||
|
target: 'es2020',
|
||||||
|
supported: {
|
||||||
|
'top-level-await': true
|
||||||
|
}
|
||||||
|
},
|
||||||
build: {
|
build: {
|
||||||
|
target: ['es2020', 'chrome87', 'firefox78', 'safari14', 'edge88'],
|
||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
// https://rollupjs.org/configuration-options/
|
// https://rollupjs.org/configuration-options/
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
|
|
|
@ -4434,6 +4434,18 @@ automation-events@^7.0.9:
|
||||||
"@babel/runtime" "^7.27.6"
|
"@babel/runtime" "^7.27.6"
|
||||||
tslib "^2.8.1"
|
tslib "^2.8.1"
|
||||||
|
|
||||||
|
autoprefixer@10.4.21:
|
||||||
|
version "10.4.21"
|
||||||
|
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.21.tgz#77189468e7a8ad1d9a37fbc08efc9f480cf0a95d"
|
||||||
|
integrity sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==
|
||||||
|
dependencies:
|
||||||
|
browserslist "^4.24.4"
|
||||||
|
caniuse-lite "^1.0.30001702"
|
||||||
|
fraction.js "^4.3.7"
|
||||||
|
normalize-range "^0.1.2"
|
||||||
|
picocolors "^1.1.1"
|
||||||
|
postcss-value-parser "^4.2.0"
|
||||||
|
|
||||||
available-typed-arrays@^1.0.7:
|
available-typed-arrays@^1.0.7:
|
||||||
version "1.0.7"
|
version "1.0.7"
|
||||||
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846"
|
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846"
|
||||||
|
@ -4647,7 +4659,7 @@ browserify-zlib@^0.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
pako "~1.0.5"
|
pako "~1.0.5"
|
||||||
|
|
||||||
browserslist@^4.24.0, browserslist@^4.25.1:
|
browserslist@^4.24.0, browserslist@^4.24.4, browserslist@^4.25.1:
|
||||||
version "4.25.1"
|
version "4.25.1"
|
||||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.25.1.tgz#ba9e8e6f298a1d86f829c9b975e07948967bb111"
|
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.25.1.tgz#ba9e8e6f298a1d86f829c9b975e07948967bb111"
|
||||||
integrity sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==
|
integrity sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==
|
||||||
|
@ -4783,6 +4795,11 @@ callsites@^3.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
|
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
|
||||||
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
|
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
|
||||||
|
|
||||||
|
caniuse-lite@^1.0.30001702:
|
||||||
|
version "1.0.30001731"
|
||||||
|
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001731.tgz#277c07416ea4613ec564e5b0ffb47e7b60f32e2f"
|
||||||
|
integrity sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg==
|
||||||
|
|
||||||
caniuse-lite@^1.0.30001726:
|
caniuse-lite@^1.0.30001726:
|
||||||
version "1.0.30001727"
|
version "1.0.30001727"
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz#22e9706422ad37aa50556af8c10e40e2d93a8b85"
|
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz#22e9706422ad37aa50556af8c10e40e2d93a8b85"
|
||||||
|
@ -6411,6 +6428,11 @@ form-data@^4.0.0, form-data@~4.0.0:
|
||||||
hasown "^2.0.2"
|
hasown "^2.0.2"
|
||||||
mime-types "^2.1.12"
|
mime-types "^2.1.12"
|
||||||
|
|
||||||
|
fraction.js@^4.3.7:
|
||||||
|
version "4.3.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7"
|
||||||
|
integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==
|
||||||
|
|
||||||
fs-extra@^11.2.0:
|
fs-extra@^11.2.0:
|
||||||
version "11.3.0"
|
version "11.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.3.0.tgz#0daced136bbaf65a555a326719af931adc7a314d"
|
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.3.0.tgz#0daced136bbaf65a555a326719af931adc7a314d"
|
||||||
|
@ -8215,6 +8237,11 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||||
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
||||||
|
|
||||||
|
normalize-range@^0.1.2:
|
||||||
|
version "0.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
|
||||||
|
integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
|
||||||
|
|
||||||
npm-run-path@^4.0.0:
|
npm-run-path@^4.0.0:
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
|
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
|
||||||
|
@ -8790,7 +8817,12 @@ postcss-selector-parser@^6.0.15:
|
||||||
cssesc "^3.0.0"
|
cssesc "^3.0.0"
|
||||||
util-deprecate "^1.0.2"
|
util-deprecate "^1.0.2"
|
||||||
|
|
||||||
postcss@^8.4.32, postcss@^8.4.38, postcss@^8.4.43, postcss@^8.4.48, postcss@^8.5.6:
|
postcss-value-parser@^4.2.0:
|
||||||
|
version "4.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
|
||||||
|
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
||||||
|
|
||||||
|
postcss@8.5.6, postcss@^8.4.32, postcss@^8.4.38, postcss@^8.4.43, postcss@^8.4.48, postcss@^8.5.6:
|
||||||
version "8.5.6"
|
version "8.5.6"
|
||||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c"
|
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c"
|
||||||
integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==
|
integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==
|
||||||
|
|
Ładowanie…
Reference in New Issue