Skip to content

Commit

Permalink
Fix textual access mode inference with FXL (#81)
Browse files Browse the repository at this point in the history
  • Loading branch information
mickael-menu authored Sep 6, 2023
1 parent f551675 commit 70e1626
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 43 deletions.
37 changes: 1 addition & 36 deletions pkg/parser/epub/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,9 @@ func (f PublicationFactory) Create() manifest.Manifest {
readingOrder = append(readingOrder, f.computeLink(item, []string{}))
}
}
readingOrderAllIds := f.computeIdsWithFallbacks(readingOrderIds)
var resourceItems []Item
for _, item := range mani {
if !extensions.Contains(readingOrderAllIds, item.ID) {
if !extensions.Contains(readingOrderIds, item.ID) {
resourceItems = append(resourceItems, item)
}
}
Expand Down Expand Up @@ -144,40 +143,6 @@ func mapEPUBLink(link EPUBLink) manifest.Link {
return l
}

// Recursively find the ids of the fallback items in [items]
func (f PublicationFactory) computeIdsWithFallbacks(ids []string) []string {
var fallbackIds []string
for _, id := range ids {
for _, v := range f.computeFallbackChain(id) {
if !extensions.Contains(fallbackIds, v) {
fallbackIds = append(fallbackIds, v)
}
}
}
return fallbackIds
}

// Compute the ids contained in the fallback chain of [item]
func (f PublicationFactory) computeFallbackChain(id string) []string {
// The termination has already been checked while computing links
var ids []string
item, ok := f.itemById[id]
if !ok {
return ids
}
if item.ID != "" {
ids = append(ids, item.ID)
}
if item.fallback != "" {
for _, v := range f.computeFallbackChain(item.fallback) {
if !extensions.Contains(ids, v) {
ids = append(ids, v)
}
}
}
return ids
}

// Compute a Publication [Link] for an epub [Item] and its fallbacks
func (f PublicationFactory) computeLink(item Item, fallbackChain []string) manifest.Link {
itemref, _ := f.itemrefByIdref[item.ID]
Expand Down
12 changes: 8 additions & 4 deletions pkg/streamer/a11y_infer.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,14 @@ func inferA11yMetadataFromManifest(mf manifest.Manifest) *manifest.A11y {
// Inferred textual if the publication is partially or fully accessible
// (WCAG A or above).
isTextual := conformsToWCAGA
if !isTextual {
// ... or if the publication does not contain any image, audio or video
// resource (inspect "resources" and "readingOrder" in RWPM), or if the
// only image available can be identified as a cover.

// ... or if a reflowable EPUB does not contain any image, audio or
// video resource (inspect "resources" and "readingOrder" in RWPM), or
// if the only image available can be identified as a cover.
if !isTextual &&
mf.ConformsTo(manifest.ProfileEPUB) &&
mf.Metadata.Presentation != nil &&
*mf.Metadata.Presentation.Layout == manifest.EPUBLayoutReflowable {
isTextual = true
for _, link := range allResources {
mt := link.MediaType()
Expand Down
51 changes: 48 additions & 3 deletions pkg/streamer/a11y_infer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ func TestReturnsAdditionalInferredA11yMetadata(t *testing.T) {

m := manifest.Manifest{
Metadata: manifest.Metadata{
ConformsTo: manifest.Profiles{manifest.ProfileEPUB},
Accessibility: &a11y,
Presentation: newEPUBPresentation(manifest.EPUBLayoutReflowable),
},
ReadingOrder: []manifest.Link{
newLink(mediatype.HTML, "html"),
Expand Down Expand Up @@ -91,7 +93,7 @@ func TestInferTextualAccessModeAndAccessModeSufficientFromProfile(t *testing.T)
test(manifest.EPUBA11y10WCAG20AAA)
}

// Or if the publication does not contain any image, audio or video resource
// Or if a reflowable EPUB does not contain any image, audio or video resource
// (inspect "resources" and "readingOrder" in RWPM)
func TestInferTextualAccessModeAndAccessModeSufficientFromLackOfMedia(t *testing.T) {
testManifest := func(contains bool, m manifest.Manifest) {
Expand All @@ -113,7 +115,11 @@ func TestInferTextualAccessModeAndAccessModeSufficientFromLackOfMedia(t *testing

testReadingOrder := func(contains bool, mt mediatype.MediaType, extension string) {
testManifest(contains, manifest.Manifest{
Metadata: manifest.Metadata{Accessibility: &a11y},
Metadata: manifest.Metadata{
ConformsTo: manifest.Profiles{manifest.ProfileEPUB},
Accessibility: &a11y,
Presentation: newEPUBPresentation(manifest.EPUBLayoutReflowable),
},
ReadingOrder: []manifest.Link{newLink(mt, extension)},
TableOfContents: []manifest.Link{newLink(mt, extension)},
})
Expand All @@ -127,7 +133,12 @@ func TestInferTextualAccessModeAndAccessModeSufficientFromLackOfMedia(t *testing

testResources := func(contains bool, mt mediatype.MediaType, extension string) {
testManifest(contains, manifest.Manifest{
Metadata: manifest.Metadata{Accessibility: &a11y},
Metadata: manifest.Metadata{
ConformsTo: manifest.Profiles{manifest.ProfileEPUB},
Accessibility: &a11y,
Presentation: newEPUBPresentation(manifest.EPUBLayoutReflowable),
},
ReadingOrder: []manifest.Link{newLink(mt, extension)},
Resources: []manifest.Link{newLink(mt, extension)},
TableOfContents: []manifest.Link{newLink(mt, extension)},
})
Expand All @@ -140,10 +151,35 @@ func TestInferTextualAccessModeAndAccessModeSufficientFromLackOfMedia(t *testing
testResources(false, mediatype.PDF, "pdf")
}

// ... but not for FXL EPUB
func TestDontInferTextualAccessModeAndAccessModeSufficientFromLackOfMediaForFXL(t *testing.T) {
a11y := manifest.NewA11y()
a11y.ConformsTo = []manifest.A11yProfile{"unknown"}

m := manifest.Manifest{
Metadata: manifest.Metadata{
ConformsTo: manifest.Profiles{manifest.ProfileEPUB},
Accessibility: &a11y,
Presentation: newEPUBPresentation(manifest.EPUBLayoutFixed),
},
ReadingOrder: []manifest.Link{newLink(mediatype.HTML, "html")},
TableOfContents: []manifest.Link{newLink(mediatype.HTML, "html")},
}

res := inferA11yMetadataFromManifest(m)
assert.NotNil(t, res)
ams := []manifest.A11yPrimaryAccessMode{manifest.A11yPrimaryAccessModeTextual}
assert.NotContains(t, res.AccessModes, manifest.A11yAccessModeTextual)
assert.NotContains(t, res.AccessModesSufficient, ams)
}

// If the publication contains only references to audio resources (inspect "resources" and "readingOrder" in RWPM)
func TestInferAuditoryAccessModeSufficient(t *testing.T) {
testManifest := func(contains bool, m manifest.Manifest) {
res := inferA11yMetadataFromManifest(m)
if res == nil && !contains {
return
}
assert.NotNil(t, res)
ams := []manifest.A11yPrimaryAccessMode{manifest.A11yPrimaryAccessModeAuditory}

Expand Down Expand Up @@ -187,6 +223,9 @@ func TestInferAuditoryAccessModeSufficient(t *testing.T) {
func TestInferVisualAccessModeSufficient(t *testing.T) {
testManifest := func(contains bool, m manifest.Manifest) {
res := inferA11yMetadataFromManifest(m)
if res == nil && !contains {
return
}
assert.NotNil(t, res)
ams := []manifest.A11yPrimaryAccessMode{manifest.A11yPrimaryAccessModeVisual}

Expand Down Expand Up @@ -330,3 +369,9 @@ func assertFeature(t *testing.T, m manifest.Manifest, feature manifest.A11yFeatu
assert.NotNil(t, res)
assert.Contains(t, res.Features, feature)
}

func newEPUBPresentation(layout manifest.EPUBLayout) *manifest.Presentation {
pres := manifest.NewPresentation()
pres.Layout = &layout
return pres
}

0 comments on commit 70e1626

Please sign in to comment.