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

Add partial support for sections properties #47

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,15 @@ If EPUBCheck is installed locally, it will be run alongside the Go tests. To ins
1. Download and extract EPUBCheck in the root directory of this project, e.g.

```
wget https://github.com/IDPF/epubcheck/releases/download/v4.2.5/epubcheck-4.2.5.zip
unzip epubcheck-4.2.5.zip
wget https://github.com/IDPF/epubcheck/releases/download/v5.1.0/epubcheck-5.1.0.zip
unzip epubcheck-5.1.0.zip
```

You can use this command to download and extract the latest versions of EPUBCheck (recommended).

```
curl -s https://api.github.com/repos/w3c/epubcheck/releases/latest | awk -F': "' '/browser_download_url/ && /epubcheck/ {gsub(/"$/, "", $2); print $2}' | xargs curl -Lo epubcheck.zip
unzip epubcheck.zip
```
Comment on lines 37 to 49

Choose a reason for hiding this comment

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

we can just keep Curl command

Copy link
Author

Choose a reason for hiding this comment

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

It's what you proposed in the previous pull request.

Choose a reason for hiding this comment

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

yes


If you do not wish to install EPUBCheck locally, you can manually validate the EPUB:
Expand Down
50 changes: 44 additions & 6 deletions epub.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ Basic usage:
package epub

import (
"bytes"
"encoding/xml"
"fmt"
"io/fs"
"log"
Expand Down Expand Up @@ -156,9 +158,10 @@ type epubCover struct {
}

type epubSection struct {
filename string
xhtml *xhtml
children []*epubSection
filename string
xhtml *xhtml
children []*epubSection
properties string
}

// NewEpub returns a new Epub.
Expand Down Expand Up @@ -377,9 +380,10 @@ func (e *Epub) addSection(parentFilename string, body string, sectionTitle strin
}

s := &epubSection{
filename: internalFilename,
xhtml: x,
children: nil,
filename: internalFilename,
xhtml: x,
children: nil,
properties: propertiesFromBody(body),
}

// section have parentIndex -1 and subsection have parrentindex != -1
Expand All @@ -397,6 +401,40 @@ func (e *Epub) addSection(parentFilename string, body string, sectionTitle strin
return internalFilename, nil
}

// supports mathml, svg, scripted
// does not support remote-sources, switch (deprecated)
func propertiesFromBody(body string) string {
prop := map[string]bool{}

decoder := xml.NewDecoder(bytes.NewBufferString(body))
for {
t, _ := decoder.Token()
if t == nil {
break
}
switch se := t.(type) {
case xml.StartElement:
switch strings.ToUpper(se.Name.Local) {
case "SVG":
prop["svg"] = true
case "MATH":
if se.Name.Space == "http://www.w3.org/1998/Math/MathML" {
prop["mathml"] = true
}
case "SCRIPT", "FORM":
prop["scripted"] = true
}
default:
}
}

ret := []string{}
for k := range prop {
ret = append(ret, k)
}
return strings.Join(ret, " ")
}

// Author returns the author of the EPUB.
func (e *Epub) Author() string {
return e.author
Expand Down
53 changes: 53 additions & 0 deletions epub_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1480,3 +1480,56 @@ func TestAddSubSectionWithCustomFilename(t *testing.T) {

cleanup(testEpubFilename, tempDir)
}

func TestSectionProperties(t *testing.T) {
e, err := NewEpub(testEpubTitle)
if err != nil {
t.Error(err)
}

_, err = e.AddSection("<h1>Section 1</h1>", "Section 1", "section0001.xhtml", "")
if err != nil {
t.Errorf("Error adding section: %s", err)
}

_, err = e.AddSection("<h1>Section 2</h1><p><svg xmlns='http://www.w3.org/2000/svg'></svg></p>", "Section 2", "section0002.xhtml", "")
if err != nil {
t.Errorf("Error adding section: %s", err)
}

_, err = e.AddSection("<h1>Section 3</h1><p><script></script></p>", "Section 3", "section0003.xhtml", "")
if err != nil {
t.Errorf("Error adding section: %s", err)
}

_, err = e.AddSection(`<h1>Section 4</h1><form></form>`, "Section 4", "section0004.xhtml", "")
if err != nil {
t.Errorf("Error adding section: %s", err)
}

_, err = e.AddSection("<h1>Section 5</h1><p><math xmlns='http://www.w3.org/1998/Math/MathML'></math></p>", "Section 5", "section0005.xhtml", "")
if err != nil {
t.Errorf("Error adding section: %s", err)
}

tempDir := writeAndExtractEpub(t, e, testEpubFilename)

output, err := validateEpub(t, testEpubFilename)
if err != nil {
t.Errorf("EPUB validation failed")
}

// Always print the output so we can see warnings as well
if output != nil {
fmt.Println(string(output))
}
if doCleanup {
cleanup(testEpubFilename, tempDir)
} else {
// Always remove the files in tempDir; they can still be extracted from the test epub as needed
err := filesystem.RemoveAll(tempDir)
if err != nil {
log.Print("Error removing temp directory: %w", err)
}
}
}
3 changes: 2 additions & 1 deletion toc.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/xml"
"fmt"
"log"
"path"
"path/filepath"
"regexp"
"strconv"
Expand Down Expand Up @@ -174,7 +175,7 @@ func (t *toc) addSubSection(parent string, index int, title string, relativePath
t.ncxXML.NavMap = append(t.ncxXML.NavMap, np)
} else {

parentRelativePath := filepath.Join(xhtmlFolderName, parent)
parentRelativePath := path.Join(xhtmlFolderName, parent)

Choose a reason for hiding this comment

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

why change filepath to path?
filepath choose the target runtime's file separators OS so it work correctly on window and Linux that has different separator

Copy link
Author

Choose a reason for hiding this comment

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

It's a fix for #46.


l := &tocNavItem{
A: tocNavLink{
Expand Down
2 changes: 1 addition & 1 deletion write.go
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ func writeSections(rootEpubDir string, e *Epub, sections []*epubSection, parentf
if section.filename != e.cover.xhtmlFilename {
e.pkg.addToSpine(section.filename)
}
e.pkg.addToManifest(section.filename, relativePath, mediaTypeXhtml, "")
e.pkg.addToManifest(section.filename, relativePath, mediaTypeXhtml, section.properties)
if parentfilename[section.filename] == "-1" && section.filename != e.cover.xhtmlFilename {
j := filenamelist[section.filename]
e.toc.addSubSection("-1", j, section.xhtml.Title(), relativePath)
Expand Down
Loading