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 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
2 changes: 1 addition & 1 deletion pkg/manifest/contributor.go
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ import (

// Contributor
// https://github.com/readium/webpub-manifest/tree/master/contexts/default#contributors
// https://github.com/readium/webpub-manifest/schema/contributor-object.schema.json
// https://github.com/readium/webpub-manifest/blob/master/schema/contributor-object.schema.json
type Contributor struct {
LocalizedName LocalizedString `json:"name" validate:"required"` // The name of the contributor.
LocalizedSortAs *LocalizedString `json:"sortAs,omitempty"` // The string used to sort the name of the contributor.
106 changes: 73 additions & 33 deletions pkg/parser/epub/metadata.go
Original file line number Diff line number Diff line change
@@ -205,7 +205,7 @@ func (m MetadataParser) parseMetaElement(element *xmlquery.Node) *MetadataItem {
id: element.SelectAttr("id"),
}
} else {
propName := strings.TrimSpace(element.SelectAttr("property"))
propName := strings.TrimSpace(property)
if propName == "" {
return nil
}
@@ -238,7 +238,7 @@ func (m MetadataParser) parseDcElement(element *xmlquery.Node) *MetadataItem {
}

data := strings.ToLower(element.Data)
propName := VocabularyDCTerms + data
propName := VocabularyDCTerms + element.Data
switch data {
case "creator":
fallthrough
@@ -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)