kopia lustrzana https://github.com/badgen/badgen
feat: add accessible text alternative in SVG (#62)
* feat: accessible text alternative in SVG * fix: change alt text strategy to support IE 11pull/63/head
rodzic
49f8e3d9b4
commit
179a1d3c2a
35
src/index.ts
35
src/index.ts
|
@ -49,14 +49,16 @@ export function badgen ({
|
|||
|
||||
label = sanitize(label)
|
||||
status = sanitize(status)
|
||||
const accessibleText = createAccessibleText({label, status})
|
||||
|
||||
if (style === 'flat') {
|
||||
return `<svg width="${scale * width / 10}" height="${scale * 20}" viewBox="0 0 ${width} 200" xmlns="http://www.w3.org/2000/svg"${xlink}>
|
||||
return `<svg width="${scale * width / 10}" height="${scale * 20}" viewBox="0 0 ${width} 200" xmlns="http://www.w3.org/2000/svg"${xlink} role="img" aria-label="${sanitizeAttribute(accessibleText)}">
|
||||
<title>${accessibleText}</title>
|
||||
<g>
|
||||
<rect fill="#${labelColor}" width="${sbRectWidth}" height="200"/>
|
||||
<rect fill="#${color}" x="${sbRectWidth}" width="${stRectWidth}" height="200"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<text x="${sbTextStart + 10}" y="148" textLength="${sbTextWidth}" fill="#000" opacity="0.1">${label}</text>
|
||||
<text x="${sbTextStart}" y="138" textLength="${sbTextWidth}">${label}</text>
|
||||
<text x="${sbRectWidth + 55}" y="148" textLength="${stTextWidth}" fill="#000" opacity="0.1">${status}</text>
|
||||
|
@ -66,7 +68,8 @@ export function badgen ({
|
|||
</svg>`
|
||||
}
|
||||
|
||||
return `<svg width="${scale * width / 10}" height="${scale * 20}" viewBox="0 0 ${width} 200" xmlns="http://www.w3.org/2000/svg"${xlink}>
|
||||
return `<svg width="${scale * width / 10}" height="${scale * 20}" viewBox="0 0 ${width} 200" xmlns="http://www.w3.org/2000/svg"${xlink} role="img" aria-label="${sanitizeAttribute(accessibleText)}">
|
||||
<title>${accessibleText}</title>
|
||||
<linearGradient id="a" x2="0" y2="100%">
|
||||
<stop offset="0" stop-opacity=".1" stop-color="#EEE"/>
|
||||
<stop offset="1" stop-opacity=".1"/>
|
||||
|
@ -77,7 +80,7 @@ export function badgen ({
|
|||
<rect width="${stRectWidth}" height="200" fill="#${color}" x="${sbRectWidth}"/>
|
||||
<rect width="${width}" height="200" fill="url(#a)"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<text x="${sbTextStart + 10}" y="148" textLength="${sbTextWidth}" fill="#000" opacity="0.25">${label}</text>
|
||||
<text x="${sbTextStart}" y="138" textLength="${sbTextWidth}">${label}</text>
|
||||
<text x="${sbRectWidth + 55}" y="148" textLength="${stTextWidth}" fill="#000" opacity="0.25">${status}</text>
|
||||
|
@ -97,18 +100,20 @@ function bare ({ status, color, style }) {
|
|||
status = sanitize(status)
|
||||
|
||||
if (style === 'flat') {
|
||||
return `<svg width="${stRectWidth / 10}" height="20" viewBox="0 0 ${stRectWidth} 200" xmlns="http://www.w3.org/2000/svg">
|
||||
return `<svg width="${stRectWidth / 10}" height="20" viewBox="0 0 ${stRectWidth} 200" xmlns="http://www.w3.org/2000/svg" role="img" aria-labeled="${sanitizeAttribute(status)}">
|
||||
<title>${status}</title>
|
||||
<g>
|
||||
<rect fill="#${color}" x="0" width="${stRectWidth}" height="200"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<text x="65" y="148" textLength="${stTextWidth}" fill="#000" opacity="0.1">${status}</text>
|
||||
<text x="55" y="138" textLength="${stTextWidth}">${status}</text>
|
||||
</g>
|
||||
</svg>`
|
||||
}
|
||||
|
||||
return `<svg width="${stRectWidth / 10}" height="20" viewBox="0 0 ${stRectWidth} 200" xmlns="http://www.w3.org/2000/svg">
|
||||
return `<svg width="${stRectWidth / 10}" height="20" viewBox="0 0 ${stRectWidth} 200" xmlns="http://www.w3.org/2000/svg" role="img" aria-labeled="${sanitizeAttribute(status)}">
|
||||
<title>${status}</title>
|
||||
<linearGradient id="a" x2="0" y2="100%">
|
||||
<stop offset="0" stop-opacity=".1" stop-color="#EEE"/>
|
||||
<stop offset="1" stop-opacity=".1"/>
|
||||
|
@ -118,7 +123,7 @@ function bare ({ status, color, style }) {
|
|||
<rect width="${stRectWidth}" height="200" fill="#${color}" x="0"/>
|
||||
<rect width="${stRectWidth}" height="200" fill="url(#a)"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<text x="65" y="148" textLength="${stTextWidth}" fill="#000" opacity="0.25">${status}</text>
|
||||
<text x="55" y="138" textLength="${stTextWidth}">${status}</text>
|
||||
</g>
|
||||
|
@ -129,6 +134,20 @@ function sanitize (str: string): string {
|
|||
return str.replace(/\u0026/g, '&').replace(/\u003C/g, '<')
|
||||
}
|
||||
|
||||
function sanitizeAttribute (str: string): string {
|
||||
return str.replace(/\u0022/g, '\"')
|
||||
}
|
||||
|
||||
interface AccessibleTextProps {
|
||||
status: string;
|
||||
label?: string;
|
||||
}
|
||||
|
||||
function createAccessibleText({label, status}: AccessibleTextProps): string {
|
||||
const labelPrefix = label ? `${label}: ` : '';
|
||||
return labelPrefix + status;
|
||||
}
|
||||
|
||||
function typeAssert (assertion: boolean, message: string): void {
|
||||
if (!assertion) throw new TypeError(message)
|
||||
}
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
*/
|
||||
'use strict'
|
||||
exports[`test/badgen.spec.ts TAP generate badge with { label, status } > snapshot 1`] = `
|
||||
<svg width="80.4" height="20" viewBox="0 0 804 200" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="80.4" height="20" viewBox="0 0 804 200" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="npm: v1.0.0">
|
||||
<title>npm: v1.0.0</title>
|
||||
<linearGradient id="a" x2="0" y2="100%">
|
||||
<stop offset="0" stop-opacity=".1" stop-color="#EEE"/>
|
||||
<stop offset="1" stop-opacity=".1"/>
|
||||
|
@ -17,7 +18,7 @@ exports[`test/badgen.spec.ts TAP generate badge with { label, status } > snapsho
|
|||
<rect width="455" height="200" fill="#08C" x="349"/>
|
||||
<rect width="804" height="200" fill="url(#a)"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<text x="60" y="148" textLength="249" fill="#000" opacity="0.25">npm</text>
|
||||
<text x="50" y="138" textLength="249">npm</text>
|
||||
<text x="404" y="148" textLength="355" fill="#000" opacity="0.25">v1.0.0</text>
|
||||
|
@ -28,7 +29,8 @@ exports[`test/badgen.spec.ts TAP generate badge with { label, status } > snapsho
|
|||
`
|
||||
|
||||
exports[`test/badgen.spec.ts TAP generate badge with { label, status, color } > snapshot 1`] = `
|
||||
<svg width="80.4" height="20" viewBox="0 0 804 200" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="80.4" height="20" viewBox="0 0 804 200" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="npm: v1.0.0">
|
||||
<title>npm: v1.0.0</title>
|
||||
<linearGradient id="a" x2="0" y2="100%">
|
||||
<stop offset="0" stop-opacity=".1" stop-color="#EEE"/>
|
||||
<stop offset="1" stop-opacity=".1"/>
|
||||
|
@ -39,7 +41,7 @@ exports[`test/badgen.spec.ts TAP generate badge with { label, status, color } >
|
|||
<rect width="455" height="200" fill="#ADF" x="349"/>
|
||||
<rect width="804" height="200" fill="url(#a)"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<text x="60" y="148" textLength="249" fill="#000" opacity="0.25">npm</text>
|
||||
<text x="50" y="138" textLength="249">npm</text>
|
||||
<text x="404" y="148" textLength="355" fill="#000" opacity="0.25">v1.0.0</text>
|
||||
|
@ -50,12 +52,13 @@ exports[`test/badgen.spec.ts TAP generate badge with { label, status, color } >
|
|||
`
|
||||
|
||||
exports[`test/badgen.spec.ts TAP generate badge with { label, status, color, style } > snapshot 1`] = `
|
||||
<svg width="80.4" height="20" viewBox="0 0 804 200" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="80.4" height="20" viewBox="0 0 804 200" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="npm: v1.0.0">
|
||||
<title>npm: v1.0.0</title>
|
||||
<g>
|
||||
<rect fill="#555" width="349" height="200"/>
|
||||
<rect fill="#ADF" x="349" width="455" height="200"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<text x="60" y="148" textLength="249" fill="#000" opacity="0.1">npm</text>
|
||||
<text x="50" y="138" textLength="249">npm</text>
|
||||
<text x="404" y="148" textLength="355" fill="#000" opacity="0.1">v1.0.0</text>
|
||||
|
@ -66,7 +69,8 @@ exports[`test/badgen.spec.ts TAP generate badge with { label, status, color, sty
|
|||
`
|
||||
|
||||
exports[`test/badgen.spec.ts TAP generate badge with { label, status, icon } > snapshot 1`] = `
|
||||
<svg width="95.5" height="20" viewBox="0 0 955 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<svg width="95.5" height="20" viewBox="0 0 955 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" role="img" aria-label="docker: icon">
|
||||
<title>docker: icon</title>
|
||||
<linearGradient id="a" x2="0" y2="100%">
|
||||
<stop offset="0" stop-opacity=".1" stop-color="#EEE"/>
|
||||
<stop offset="1" stop-opacity=".1"/>
|
||||
|
@ -77,7 +81,7 @@ exports[`test/badgen.spec.ts TAP generate badge with { label, status, icon } > s
|
|||
<rect width="324" height="200" fill="#08C" x="631"/>
|
||||
<rect width="955" height="200" fill="url(#a)"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<text x="220" y="148" textLength="371" fill="#000" opacity="0.25">docker</text>
|
||||
<text x="210" y="138" textLength="371">docker</text>
|
||||
<text x="686" y="148" textLength="224" fill="#000" opacity="0.25">icon</text>
|
||||
|
@ -88,12 +92,13 @@ exports[`test/badgen.spec.ts TAP generate badge with { label, status, icon } > s
|
|||
`
|
||||
|
||||
exports[`test/badgen.spec.ts TAP generate badge with { label, status, icon, style } > snapshot 1`] = `
|
||||
<svg width="95.5" height="20" viewBox="0 0 955 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<svg width="95.5" height="20" viewBox="0 0 955 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" role="img" aria-label="docker: icon">
|
||||
<title>docker: icon</title>
|
||||
<g>
|
||||
<rect fill="#555" width="631" height="200"/>
|
||||
<rect fill="#08C" x="631" width="324" height="200"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<text x="220" y="148" textLength="371" fill="#000" opacity="0.1">docker</text>
|
||||
<text x="210" y="138" textLength="371">docker</text>
|
||||
<text x="686" y="148" textLength="224" fill="#000" opacity="0.1">icon</text>
|
||||
|
@ -104,12 +109,13 @@ exports[`test/badgen.spec.ts TAP generate badge with { label, status, icon, styl
|
|||
`
|
||||
|
||||
exports[`test/badgen.spec.ts TAP generate badge with { label, status, style } > snapshot 1`] = `
|
||||
<svg width="80.4" height="20" viewBox="0 0 804 200" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="80.4" height="20" viewBox="0 0 804 200" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="npm: v1.0.0">
|
||||
<title>npm: v1.0.0</title>
|
||||
<g>
|
||||
<rect fill="#555" width="349" height="200"/>
|
||||
<rect fill="#08C" x="349" width="455" height="200"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<text x="60" y="148" textLength="249" fill="#000" opacity="0.1">npm</text>
|
||||
<text x="50" y="138" textLength="249">npm</text>
|
||||
<text x="404" y="148" textLength="355" fill="#000" opacity="0.1">v1.0.0</text>
|
||||
|
@ -120,7 +126,8 @@ exports[`test/badgen.spec.ts TAP generate badge with { label, status, style } >
|
|||
`
|
||||
|
||||
exports[`test/badgen.spec.ts TAP generate badge with { status, icon } > snapshot 1`] = `
|
||||
<svg width="53.6" height="20" viewBox="0 0 536 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<svg width="53.6" height="20" viewBox="0 0 536 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" role="img" aria-label="icon">
|
||||
<title>icon</title>
|
||||
<linearGradient id="a" x2="0" y2="100%">
|
||||
<stop offset="0" stop-opacity=".1" stop-color="#EEE"/>
|
||||
<stop offset="1" stop-opacity=".1"/>
|
||||
|
@ -131,7 +138,7 @@ exports[`test/badgen.spec.ts TAP generate badge with { status, icon } > snapshot
|
|||
<rect width="324" height="200" fill="#08C" x="212"/>
|
||||
<rect width="536" height="200" fill="url(#a)"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<text x="172" y="148" textLength="0" fill="#000" opacity="0.25"></text>
|
||||
<text x="162" y="138" textLength="0"></text>
|
||||
<text x="267" y="148" textLength="224" fill="#000" opacity="0.25">icon</text>
|
||||
|
@ -142,7 +149,8 @@ exports[`test/badgen.spec.ts TAP generate badge with { status, icon } > snapshot
|
|||
`
|
||||
|
||||
exports[`test/badgen.spec.ts TAP generate badge with { status, icon, iconWidth } > snapshot 1`] = `
|
||||
<svg width="59.6" height="20" viewBox="0 0 596 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<svg width="59.6" height="20" viewBox="0 0 596 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" role="img" aria-label="icon">
|
||||
<title>icon</title>
|
||||
<linearGradient id="a" x2="0" y2="100%">
|
||||
<stop offset="0" stop-opacity=".1" stop-color="#EEE"/>
|
||||
<stop offset="1" stop-opacity=".1"/>
|
||||
|
@ -153,7 +161,7 @@ exports[`test/badgen.spec.ts TAP generate badge with { status, icon, iconWidth }
|
|||
<rect width="324" height="200" fill="#08C" x="272"/>
|
||||
<rect width="596" height="200" fill="url(#a)"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<text x="232" y="148" textLength="0" fill="#000" opacity="0.25"></text>
|
||||
<text x="222" y="138" textLength="0"></text>
|
||||
<text x="327" y="148" textLength="224" fill="#000" opacity="0.25">icon</text>
|
||||
|
@ -164,7 +172,8 @@ exports[`test/badgen.spec.ts TAP generate badge with { status, icon, iconWidth }
|
|||
`
|
||||
|
||||
exports[`test/badgen.spec.ts TAP generate bare badge with { status } > snapshot 1`] = `
|
||||
<svg width="47" height="20" viewBox="0 0 470 200" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="47" height="20" viewBox="0 0 470 200" xmlns="http://www.w3.org/2000/svg" role="img" aria-labeled="v1.0.0">
|
||||
<title>v1.0.0</title>
|
||||
<linearGradient id="a" x2="0" y2="100%">
|
||||
<stop offset="0" stop-opacity=".1" stop-color="#EEE"/>
|
||||
<stop offset="1" stop-opacity=".1"/>
|
||||
|
@ -174,7 +183,7 @@ exports[`test/badgen.spec.ts TAP generate bare badge with { status } > snapshot
|
|||
<rect width="470" height="200" fill="#08C" x="0"/>
|
||||
<rect width="470" height="200" fill="url(#a)"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<text x="65" y="148" textLength="355" fill="#000" opacity="0.25">v1.0.0</text>
|
||||
<text x="55" y="138" textLength="355">v1.0.0</text>
|
||||
</g>
|
||||
|
@ -182,7 +191,8 @@ exports[`test/badgen.spec.ts TAP generate bare badge with { status } > snapshot
|
|||
`
|
||||
|
||||
exports[`test/badgen.spec.ts TAP generate bare badge with { status, color } > snapshot 1`] = `
|
||||
<svg width="47" height="20" viewBox="0 0 470 200" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="47" height="20" viewBox="0 0 470 200" xmlns="http://www.w3.org/2000/svg" role="img" aria-labeled="v1.0.0">
|
||||
<title>v1.0.0</title>
|
||||
<linearGradient id="a" x2="0" y2="100%">
|
||||
<stop offset="0" stop-opacity=".1" stop-color="#EEE"/>
|
||||
<stop offset="1" stop-opacity=".1"/>
|
||||
|
@ -192,7 +202,7 @@ exports[`test/badgen.spec.ts TAP generate bare badge with { status, color } > sn
|
|||
<rect width="470" height="200" fill="#ADF" x="0"/>
|
||||
<rect width="470" height="200" fill="url(#a)"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<text x="65" y="148" textLength="355" fill="#000" opacity="0.25">v1.0.0</text>
|
||||
<text x="55" y="138" textLength="355">v1.0.0</text>
|
||||
</g>
|
||||
|
@ -200,11 +210,12 @@ exports[`test/badgen.spec.ts TAP generate bare badge with { status, color } > sn
|
|||
`
|
||||
|
||||
exports[`test/badgen.spec.ts TAP generate bare badge with { status, style } > snapshot 1`] = `
|
||||
<svg width="47" height="20" viewBox="0 0 470 200" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="47" height="20" viewBox="0 0 470 200" xmlns="http://www.w3.org/2000/svg" role="img" aria-labeled="v1.0.0">
|
||||
<title>v1.0.0</title>
|
||||
<g>
|
||||
<rect fill="#08C" x="0" width="470" height="200"/>
|
||||
</g>
|
||||
<g fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<g aria-hidden="true" fill="#fff" text-anchor="start" font-family="Verdana,DejaVu Sans,sans-serif" font-size="110">
|
||||
<text x="65" y="148" textLength="355" fill="#000" opacity="0.1">v1.0.0</text>
|
||||
<text x="55" y="138" textLength="355">v1.0.0</text>
|
||||
</g>
|
||||
|
|
Ładowanie…
Reference in New Issue