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

Fixes for A11y metadata #208

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Changes from 1 commit
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
Next Next commit
fixes
chocolatkey committed Mar 18, 2025
commit fb1e1f0a1feb9d00bb8cd3697247c1ba4a20b7fe
102 changes: 71 additions & 31 deletions pkg/parser/epub/metadata.go
Original file line number Diff line number Diff line change
@@ -403,13 +403,18 @@ func (m metadataAdapter) FirstValue(property string) string {
return item.value
}

func itemsValues(items []MetadataItem) []string {
values := make([]string, len(items))
for i, item := range items {
values[i] = item.value
}
return values
}

func (m metadataAdapter) Values(property string) []string {
var values []string
if items, ok := m.items[property]; ok {
values = make([]string, len(items))
for i, item := range items {
values[i] = item.value
}
values = itemsValues(items)
}
return values
}
@@ -640,18 +645,38 @@ func (m PubMetadataAdapter) LocalizedSortAs() *manifest.LocalizedString {

func (m PubMetadataAdapter) Accessibility() *manifest.A11y {
a11y := manifest.NewA11y()
a11y.ConformsTo = m.a11yConformsTo()
a11y.Certification = m.a11yCertification()
a11y.Summary = m.a11ySummary()
a11y.AccessModes = m.a11yAccessModes()
a11y.AccessModesSufficient = m.a11yAccessModesSufficient()
a11y.Features = m.a11yFeatures()
a11y.Hazards = m.a11yHazards()
a11y.Exemptions = m.a11yExemptions()
ct, refinedA11y := m.a11yConformsTo()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you be able to add test cases for this new logic with the refined metadata? https://github.com/readium/go-toolkit/blob/develop/pkg/parser/epub/metadata_test.go

a11y.ConformsTo = ct

certifierItem, _ := m.First(VocabularyA11Y + "certifiedBy")
a11y.Certification = m.a11yCertification(certifierItem)

a11y.Summary = m.FirstValue(VocabularySchema + "accessibilitySummary")

modeValues := m.Values(VocabularySchema + "accessMode")
a11y.AccessModes = valuesToAccessModes(modeValues)

sufficientValues := m.Values(VocabularySchema + "accessModeSufficient")
a11y.AccessModesSufficient = valuesToAccessModesSufficient(sufficientValues)

featureValues := m.Values(VocabularySchema + "accessibilityFeature")
a11y.Features = valuesToA11yFeatures(featureValues)

hazardValues := m.Values(VocabularySchema + "accessibilityHazard")
a11y.Hazards = valuesToA11yHazards(hazardValues)

exemptionValues := m.Values(VocabularyA11Y + "exemption")
a11y.Exemptions = valuesToA11yExemptions(exemptionValues)

if a11y.IsEmpty() {
return nil
}

// ConformsTo refinements merge with the main a11y data
if !refinedA11y.IsEmpty() {
a11y.Merge(&refinedA11y)
}

return &a11y
}

@@ -674,13 +699,32 @@ func (m PubMetadataAdapter) TDM() *manifest.TDM {
return tdm
}

func (m PubMetadataAdapter) a11yConformsTo() []manifest.A11yProfile {
func (m PubMetadataAdapter) a11yConformsTo() ([]manifest.A11yProfile, manifest.A11y) {
profiles := manifest.A11yProfileList{}
a11y := manifest.NewA11y()

if items, ok := m.items[VocabularyDCTerms+"conformsto"]; ok {
if items, ok := m.items[VocabularyDCTerms+"conformsTo"]; ok {
for _, item := range items {
if profile := a11yProfile(item.value); profile != "" {
profiles = append(profiles, profile)
for k, v := range item.children {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do I read correctly that the refined metadata of the last conformsTo declared will override all the other accessibility metadata? In which case we're loosing the other metadata (global or refined). Is this what we want @HadrienGardeur?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I'm following that one since conformsTo should be an array of URIs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand the code correctly this will parse the a11y metadata that are refining each dc:conformsTo tags. Although I didn't know that <dc:conformsTo> could be refined, I thought only <meta> with an ID could.

@chocolatkey Do you have an OPF example that this is supposed to parse?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ha I see, in that case my initial question stands. We can have several conformances with different IDs and their own refinements.

<meta id="conformance-statement" property="dcterms:conformsTo">EPUB Accessibility 1.1 - WCAG 2.2 Level AA</meta>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then it's probably a limitation of our model because the certification object isn't tied to a particular conformsTo.

I'm hesitant to shake things up though, because it seems quite unlikely that you'd get certified multiple times (in most countries, there won't be a certification process at all).

switch k {
case VocabularyA11Y + "certifiedBy":
a11y.Certification = m.a11yCertification(v[0])
case VocabularySchema + "accessibilitySummary":
a11y.Summary = v[0].value
case VocabularySchema + "accessMode":
a11y.AccessModes = valuesToAccessModes(itemsValues(v))
case VocabularySchema + "accessModeSufficient":
a11y.AccessModesSufficient = valuesToAccessModesSufficient(itemsValues(v))
case VocabularySchema + "accessibilityFeature":
a11y.Features = valuesToA11yFeatures(itemsValues(v))
case VocabularySchema + "accessibilityHazard":
a11y.Hazards = valuesToA11yHazards(itemsValues(v))
case VocabularyA11Y + "exemption":
a11y.Exemptions = valuesToA11yExemptions(itemsValues(v))
}
}
}
}
}
@@ -692,7 +736,7 @@ func (m PubMetadataAdapter) a11yConformsTo() []manifest.A11yProfile {
}

profiles.Sort()
return profiles
return profiles, a11y
}

func a11yProfile(value string) manifest.A11yProfile {
@@ -726,13 +770,18 @@ func a11yProfile(value string) manifest.A11yProfile {
return manifest.EPUBA11y11WCAG21AA
case "EPUB Accessibility 1.1 - WCAG 2.1 Level AAA":
return manifest.EPUBA11y11WCAG21AAA
case "EPUB Accessibility 1.1 - WCAG 2.2 Level A":
return manifest.EPUBA11y11WCAG22A
case "EPUB Accessibility 1.1 - WCAG 2.2 Level AA":
return manifest.EPUBA11y11WCAG22AA
case "EPUB Accessibility 1.1 - WCAG 2.2 Level AAA":
return manifest.EPUBA11y11WCAG22AAA
default:
return ""
}
}

func (m PubMetadataAdapter) a11yCertification() *manifest.A11yCertification {
certifierItem, _ := m.First(VocabularyA11Y + "certifiedBy")
func (m PubMetadataAdapter) a11yCertification(certifierItem MetadataItem) *manifest.A11yCertification {
c := manifest.A11yCertification{
CertifiedBy: certifierItem.value,
}
@@ -760,21 +809,15 @@ func (m PubMetadataAdapter) a11yCertification() *manifest.A11yCertification {
return &c
}

func (m PubMetadataAdapter) a11ySummary() string {
return m.FirstValue(VocabularySchema + "accessibilitySummary")
}

func (m PubMetadataAdapter) a11yAccessModes() []manifest.A11yAccessMode {
values := m.Values(VocabularySchema + "accessMode")
func valuesToAccessModes(values []string) []manifest.A11yAccessMode {
am := make([]manifest.A11yAccessMode, len(values))
for i, v := range values {
am[i] = manifest.A11yAccessMode(v)
}
return am
}

func (m PubMetadataAdapter) a11yAccessModesSufficient() [][]manifest.A11yPrimaryAccessMode {
values := m.Values(VocabularySchema + "accessModeSufficient")
func valuesToAccessModesSufficient(values []string) [][]manifest.A11yPrimaryAccessMode {
ams := make([][]manifest.A11yPrimaryAccessMode, 0, len(values))
for _, v := range values {
c := a11yAccessModesSufficient(v)
@@ -797,26 +840,23 @@ func a11yAccessModesSufficient(value string) []manifest.A11yPrimaryAccessMode {
return ams
}

func (m PubMetadataAdapter) a11yFeatures() []manifest.A11yFeature {
values := m.Values(VocabularySchema + "accessibilityFeature")
func valuesToA11yFeatures(values []string) []manifest.A11yFeature {
features := make([]manifest.A11yFeature, len(values))
for i, v := range values {
features[i] = manifest.A11yFeature(v)
}
return features
}

func (m PubMetadataAdapter) a11yHazards() []manifest.A11yHazard {
values := m.Values(VocabularySchema + "accessibilityHazard")
func valuesToA11yHazards(values []string) []manifest.A11yHazard {
hazards := make([]manifest.A11yHazard, len(values))
for i, v := range values {
hazards[i] = manifest.A11yHazard(v)
}
return hazards
}

func (m PubMetadataAdapter) a11yExemptions() []manifest.A11yExemption {
values := m.Values(VocabularyA11Y + "exemption")
func valuesToA11yExemptions(values []string) []manifest.A11yExemption {
exemptions := make([]manifest.A11yExemption, len(values))
for i, v := range values {
exemptions[i] = manifest.A11yExemption(v)
Loading