Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement EPUB/WebPub exemptions #184

Merged
merged 1 commit into from
Feb 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions pkg/manifest/a11y.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type A11y struct {
AccessModesSufficient [][]A11yPrimaryAccessMode `json:"accessModeSufficient,omitempty"` // A list of single or combined accessModes that are sufficient to understand all the intellectual content of a resource.
Features []A11yFeature `json:"feature,omitempty"` // Content features of the resource, such as accessible media, alternatives and supported enhancements for accessibility.
Hazards []A11yHazard `json:"hazard,omitempty"` // A characteristic of the described resource that is physiologically dangerous to some users.
Exemptions []A11yExemption `json:"exemption,omitempty"` // Justifications for non-conformance based on exemptions in a given jurisdiction.
}

// NewA11y creates a new empty A11y.
Expand All @@ -29,6 +30,7 @@ func NewA11y() A11y {
AccessModesSufficient: [][]A11yPrimaryAccessMode{},
Features: []A11yFeature{},
Hazards: []A11yHazard{},
Exemptions: []A11yExemption{},
}
}

Expand Down Expand Up @@ -130,6 +132,12 @@ func A11yFromJSON(rawJSON map[string]interface{}) (*A11y, error) {
}
a.Hazards = A11yHazardsFromStrings(hazards)

examptions, err := parseSliceOrString(rawJSON["exemption"], true)
if err != nil {
return nil, errors.Wrap(err, "failed unmarshalling 'exemption'")
}
a.Exemptions = A11yExemptionsFromStrings(examptions)

return a, nil
}

Expand Down Expand Up @@ -433,6 +441,21 @@ func A11yHazardsFromStrings(strings []string) []A11yHazard {
})
}

// A11yExemption is a justification for non-conformance based on an exemption in a given jurisdiction.
type A11yExemption string

const (
A11yExemptionEAASisproportionateBurden A11yExemption = "eaa-disproportionate-burden"
chocolatkey marked this conversation as resolved.
Show resolved Hide resolved
A11yExemptionEAAFundamentalAlteration A11yExemption = "eaa-fundamental-alteration"
A11yExemptionEAAMicroenterprise A11yExemption = "eaa-microenterprise"
)

func A11yExemptionsFromStrings(strings []string) []A11yExemption {
return fromStrings(strings, func(str string) A11yExemption {
return A11yExemption(str)
})
}

func fromStrings[T any](strings []string, transform func(string) T) []T {
res := make([]T, 0, len(strings))
for _, s := range strings {
Expand Down
14 changes: 12 additions & 2 deletions pkg/manifest/a11y_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ func TestA11yUnmarshalFullJSON(t *testing.T) {
"accessMode": ["auditory", "chartOnVisual"],
"accessModeSufficient": [["visual", "tactile"]],
"feature": ["readingOrder", "alternativeText"],
"hazard": ["flashing", "motionSimulation"]
"hazard": ["flashing", "motionSimulation"],
"exemption": ["eaa-fundamental-alteration", "eaa-microenterprise"]
}`), &m))
assert.Equal(t, A11y{
ConformsTo: []A11yProfile{
Expand Down Expand Up @@ -57,6 +58,10 @@ func TestA11yUnmarshalFullJSON(t *testing.T) {
A11yHazardFlashing,
A11yHazardMotionSimulation,
},
Exemptions: []A11yExemption{
A11yExemptionEAAFundamentalAlteration,
A11yExemptionEAAMicroenterprise,
},
}, m, "unmarshalled JSON object should be equal to A11y object")
}

Expand Down Expand Up @@ -101,6 +106,7 @@ func TestA11yMarshalMinimalJSON(t *testing.T) {
AccessModesSufficient: [][]A11yPrimaryAccessMode{},
Features: []A11yFeature{},
Hazards: []A11yHazard{},
Exemptions: []A11yExemption{},
}
data, err := json.Marshal(m)
assert.NoError(t, err)
Expand Down Expand Up @@ -139,12 +145,16 @@ func TestA11yMarshalFullJSON(t *testing.T) {
A11yHazardFlashing,
A11yHazardMotionSimulation,
},
Exemptions: []A11yExemption{
A11yExemptionEAAFundamentalAlteration,
A11yExemptionEAAMicroenterprise,
},
}
data, err := json.Marshal(m)
assert.NoError(t, err)
assert.Equal(
t,
data,
[]byte(`{"conformsTo":["http://www.idpf.org/epub/a11y/accessibility-20170105.html#wcag-a","https://profile2"],"certification":{"certifiedBy":"company1","credential":"credential1","report":"https://report1"},"summary":"Summary","accessMode":["auditory","chartOnVisual"],"accessModeSufficient":[["auditory"],["visual","tactile"],["visual"]],"feature":["readingOrder","alternativeText"],"hazard":["flashing","motionSimulation"]}`),
[]byte(`{"conformsTo":["http://www.idpf.org/epub/a11y/accessibility-20170105.html#wcag-a","https://profile2"],"certification":{"certifiedBy":"company1","credential":"credential1","report":"https://report1"},"summary":"Summary","accessMode":["auditory","chartOnVisual"],"accessModeSufficient":[["auditory"],["visual","tactile"],["visual"]],"feature":["readingOrder","alternativeText"],"hazard":["flashing","motionSimulation"],"exemption":["eaa-fundamental-alteration","eaa-microenterprise"]}`),
)
}
10 changes: 10 additions & 0 deletions pkg/parser/epub/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,7 @@ func (m PubMetadataAdapter) Accessibility() *manifest.A11y {
a11y.AccessModesSufficient = m.a11yAccessModesSufficient()
a11y.Features = m.a11yFeatures()
a11y.Hazards = m.a11yHazards()
a11y.Exemptions = m.a11yExemptions()

if a11y.IsEmpty() {
return nil
Expand Down Expand Up @@ -785,6 +786,15 @@ func (m PubMetadataAdapter) a11yHazards() []manifest.A11yHazard {
return hazards
}

func (m PubMetadataAdapter) a11yExemptions() []manifest.A11yExemption {
values := m.Values(VocabularyA11Y + "exemption")
hazards := make([]manifest.A11yExemption, len(values))
for i, v := range values {
hazards[i] = manifest.A11yExemption(v)
}
return hazards
chocolatkey marked this conversation as resolved.
Show resolved Hide resolved
}

func (m *PubMetadataAdapter) seedBelongsToData() {
if m._belongsToSeeded {
return
Expand Down
2 changes: 2 additions & 0 deletions pkg/parser/epub/metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ func TestMetadataEPUB2Accessibility(t *testing.T) {
}
e.Features = []manifest.A11yFeature{manifest.A11yFeatureStructuralNavigation, manifest.A11yFeatureAlternativeText}
e.Hazards = []manifest.A11yHazard{manifest.A11yHazardMotionSimulation, manifest.A11yHazardNoSoundHazard}
e.Exemptions = []manifest.A11yExemption{manifest.A11yExemptionEAAMicroenterprise, manifest.A11yExemptionEAAFundamentalAlteration}
assert.Equal(t, &e, m.Accessibility)
assert.Nil(t, m.OtherMetadata["accessibility"])
}
Expand All @@ -345,6 +346,7 @@ func TestMetadataEPUB3Accessibility(t *testing.T) {
}
e.Features = []manifest.A11yFeature{manifest.A11yFeatureStructuralNavigation, manifest.A11yFeatureAlternativeText}
e.Hazards = []manifest.A11yHazard{manifest.A11yHazardMotionSimulation, manifest.A11yHazardNoSoundHazard}
e.Exemptions = []manifest.A11yExemption{manifest.A11yExemptionEAAMicroenterprise, manifest.A11yExemptionEAAFundamentalAlteration}
assert.Equal(t, &e, m.Accessibility)
assert.Nil(t, m.OtherMetadata["accessibility"])
}
Expand Down
3 changes: 3 additions & 0 deletions pkg/parser/epub/testdata/package/accessibility-epub2.opf
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
<meta name="a11y:certifiedBy" content="Accessibility Testers Group"/>
<meta name="a11y:certifierCredential" content="DAISY OK"/>
<meta name="a11y:certifierReport" content="https://example.com/a11y-report/"/>

chocolatkey marked this conversation as resolved.
Show resolved Hide resolved
<meta property="a11y:exemption">eaa-microenterprise</meta>
<meta property="a11y:exemption">eaa-fundamental-alteration</meta>
</metadata>
<manifest>
<item id="titlepage" href="titlepage.xhtml"/>
Expand Down
3 changes: 3 additions & 0 deletions pkg/parser/epub/testdata/package/accessibility-epub3.opf
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
<link rel="a11y:certifierReport" refines="#certifier2" href="https://example.com/fakereport"/>
<link rel="a11y:certifierReport" refines="#certifier" href="https://example.com/a11y-report/"/>

<meta property="a11y:exemption">eaa-microenterprise</meta>
<meta property="a11y:exemption">eaa-fundamental-alteration</meta>

chocolatkey marked this conversation as resolved.
Show resolved Hide resolved
</metadata>
<manifest>
<item id="titlepage" href="titlepage.xhtml"/>
Expand Down