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

feat: Add EPUB for output option #418

Merged
merged 42 commits into from
Jul 24, 2023
Merged

feat: Add EPUB for output option #418

merged 42 commits into from
Jul 24, 2023

Conversation

spring-raining
Copy link
Member

@spring-raining spring-raining commented Jul 3, 2023

  • Supports EPUB output format
vivliostyle build -c vivliostyle.config.js -o output.epub
vivliostyle build input.md -o output.epub
  • Supports webbookwebpub/epub conversion
vivliostyle build index.html -o output -f webpub

# Supports remote HTML file (linked resources will be downloaded)
vivliostyle build https://vivliostyle.github.io/vivliostyle_doc/samples/gon/index.html -o output.epub

# Supports single-doucment publication
vivliostyle build https://www.w3.org/TR/wpub/ -o output.epub

Supported ouptuts

  • 🔵: Already supported
  • 🟢: Newly supported in this PR
Input \ Output pdf webpub epub
pub-manifest 🔵 🔵 🟢
markdown 🔵 🔵 🟢
webbook (including remote HTML files) 🔵 🟢 🟢
epub epub-opf 🔵 🙅 🙅

@spring-raining spring-raining self-assigned this Jul 3, 2023
@spring-raining spring-raining marked this pull request as ready for review July 15, 2023 16:17
@MurakamiShinyu
Copy link
Member

EPUB生成を試してみました。
EPUBに不必要なファイルがEPUBに含まれてしまうことが気になります。

テストの素材として https://github.com/spring-raining/tbf13-draft を使いました。

vivliostyle-cliのこのPRをビルドしてから、その親のディレクトリで

$ git clone https://github.com/spring-raining/tbf13-draft.git
$ cd tbf13-draft

まず、PDFを生成してみる:

$ ../vivliostyle-cli/dist/cli.js build

これでPDFファイル tbf13-draft.pdf が生成できた。次にEPUBの生成をテスト:

$ ../vivliostyle-cli/dist/cli.js build -o tbf13-draft.epub
◡ Collecting build config
tbf13-draft.epub has been created.
🎉 Built successfully.

この生成されたEPUBをunzipして中身を確認する:

$ unzip tbf13-draft.epub -d epub-exp
Archive:  tbf13-draft.epub
 extracting: epub-exp/mimetype       
 extracting: epub-exp/META-INF/container.xml  
   creating: epub-exp/EPUB/.git/
 extracting: epub-exp/EPUB/.git/HEAD  
 extracting: epub-exp/EPUB/.git/config  
 extracting: epub-exp/EPUB/.git/description  
   creating: epub-exp/EPUB/.git/hooks/
 extracting: epub-exp/EPUB/.git/hooks/applypatch-msg.sample  
 extracting: epub-exp/EPUB/.git/hooks/commit-msg.sample  
 extracting: epub-exp/EPUB/.git/hooks/fsmonitor-watchman.sample  
 extracting: epub-exp/EPUB/.git/hooks/post-update.sample  
 extracting: epub-exp/EPUB/.git/hooks/pre-applypatch.sample  
 extracting: epub-exp/EPUB/.git/hooks/pre-commit.sample  
 extracting: epub-exp/EPUB/.git/hooks/pre-merge-commit.sample  
 extracting: epub-exp/EPUB/.git/hooks/pre-push.sample  
 extracting: epub-exp/EPUB/.git/hooks/pre-rebase.sample  
 extracting: epub-exp/EPUB/.git/hooks/pre-receive.sample  
 extracting: epub-exp/EPUB/.git/hooks/prepare-commit-msg.sample  
 extracting: epub-exp/EPUB/.git/hooks/push-to-checkout.sample  
 extracting: epub-exp/EPUB/.git/hooks/update.sample  
 extracting: epub-exp/EPUB/.git/index  
   creating: epub-exp/EPUB/.git/info/
 extracting: epub-exp/EPUB/.git/info/exclude  
   creating: epub-exp/EPUB/.git/logs/
 extracting: epub-exp/EPUB/.git/logs/HEAD  
   creating: epub-exp/EPUB/.git/logs/refs/
   creating: epub-exp/EPUB/.git/logs/refs/heads/
 extracting: epub-exp/EPUB/.git/logs/refs/heads/main  
   creating: epub-exp/EPUB/.git/logs/refs/remotes/
   creating: epub-exp/EPUB/.git/logs/refs/remotes/origin/
 extracting: epub-exp/EPUB/.git/logs/refs/remotes/origin/HEAD  
   creating: epub-exp/EPUB/.git/objects/
   creating: epub-exp/EPUB/.git/objects/pack/
 extracting: epub-exp/EPUB/.git/objects/pack/pack-f5710a47adb05d8212b9f3d6c4d09e9fc3fbd230.idx  
 extracting: epub-exp/EPUB/.git/objects/pack/pack-f5710a47adb05d8212b9f3d6c4d09e9fc3fbd230.pack  
 extracting: epub-exp/EPUB/.git/packed-refs  
   creating: epub-exp/EPUB/.git/refs/
   creating: epub-exp/EPUB/.git/refs/heads/
 extracting: epub-exp/EPUB/.git/refs/heads/main  
   creating: epub-exp/EPUB/.git/refs/remotes/
   creating: epub-exp/EPUB/.git/refs/remotes/origin/
 extracting: epub-exp/EPUB/.git/refs/remotes/origin/HEAD  
   creating: epub-exp/EPUB/.github/
   creating: epub-exp/EPUB/.github/workflows/
 extracting: epub-exp/EPUB/.github/workflows/build-book.yml  
 extracting: epub-exp/EPUB/LICENSE   
 extracting: epub-exp/EPUB/README.md  
   creating: epub-exp/EPUB/content/
   creating: epub-exp/EPUB/content/akabeko/
 extracting: epub-exp/EPUB/content/akabeko/index.md  
 extracting: epub-exp/EPUB/content/akabeko/index.xhtml  
   creating: epub-exp/EPUB/content/assets/
 extracting: epub-exp/EPUB/content/assets/MurakamiShinyu.jpeg  
 extracting: epub-exp/EPUB/content/assets/akabeko.png  
 extracting: epub-exp/EPUB/content/assets/mh35.jpeg  
 extracting: epub-exp/EPUB/content/assets/ogwata.png  
 extracting: epub-exp/EPUB/content/assets/spring-raining.png  
 extracting: epub-exp/EPUB/content/atogaki.md  
 extracting: epub-exp/EPUB/content/atogaki.xhtml  
 extracting: epub-exp/EPUB/content/index.md  
 extracting: epub-exp/EPUB/content/index.xhtml  
 extracting: epub-exp/EPUB/content/maegaki.md  
 extracting: epub-exp/EPUB/content/maegaki.xhtml  
   creating: epub-exp/EPUB/content/mh35/
 extracting: epub-exp/EPUB/content/mh35/index.md  
 extracting: epub-exp/EPUB/content/mh35/index.xhtml  
   creating: epub-exp/EPUB/content/ogwata/
   creating: epub-exp/EPUB/content/ogwata/image/
 extracting: epub-exp/EPUB/content/ogwata/image/fig-1.png  
 extracting: epub-exp/EPUB/content/ogwata/image/fig-2.png  
 extracting: epub-exp/EPUB/content/ogwata/image/fig-3.png  
 extracting: epub-exp/EPUB/content/ogwata/index.md  
 extracting: epub-exp/EPUB/content/ogwata/index.xhtml  
   creating: epub-exp/EPUB/content/shinyu/
   creating: epub-exp/EPUB/content/shinyu/images/
 extracting: epub-exp/EPUB/content/shinyu/images/css-grid.png  
 extracting: epub-exp/EPUB/content/shinyu/index.md  
 extracting: epub-exp/EPUB/content/shinyu/index.xhtml  
   creating: epub-exp/EPUB/content/spring-raining/
   creating: epub-exp/EPUB/content/spring-raining/assets/
 extracting: epub-exp/EPUB/content/spring-raining/assets/chart-css-screenshot.png  
 extracting: epub-exp/EPUB/content/spring-raining/index.md  
 extracting: epub-exp/EPUB/content/spring-raining/index.xhtml  
 extracting: epub-exp/EPUB/content.opf  
 extracting: epub-exp/EPUB/package-lock.json  
 extracting: epub-exp/EPUB/package.json  
 extracting: epub-exp/EPUB/publication.json  
 extracting: epub-exp/EPUB/tbf13-draft.pdf  
   creating: epub-exp/EPUB/theme/
 extracting: epub-exp/EPUB/theme/font.css  
   creating: epub-exp/EPUB/theme/lib/
   creating: epub-exp/EPUB/theme/lib/prism/
 extracting: epub-exp/EPUB/theme/lib/prism/base.css  
 extracting: epub-exp/EPUB/theme/lib/prism/theme-okaidia.css  
 extracting: epub-exp/EPUB/theme/lib/prism/theme-prism.css  
 extracting: epub-exp/EPUB/theme/package.json  
   creating: epub-exp/EPUB/theme/partial/
 extracting: epub-exp/EPUB/theme/partial/base.css  
 extracting: epub-exp/EPUB/theme/partial/crossref-counter.css  
 extracting: epub-exp/EPUB/theme/partial/footnote-external-link.css  
 extracting: epub-exp/EPUB/theme/partial/footnote.css  
 extracting: epub-exp/EPUB/theme/partial/page-counter.css  
 extracting: epub-exp/EPUB/theme/partial/page-media.css  
 extracting: epub-exp/EPUB/theme/partial/reset.css  
 extracting: epub-exp/EPUB/theme/partial/section-counter.css  
 extracting: epub-exp/EPUB/theme/partial/toc.css  
 extracting: epub-exp/EPUB/theme/partial/variable.css  
 extracting: epub-exp/EPUB/theme/theme_common.css  
 extracting: epub-exp/EPUB/theme/theme_print.css  
 extracting: epub-exp/EPUB/theme/theme_screen.css  
 extracting: epub-exp/EPUB/toc.ncx   
 extracting: epub-exp/EPUB/vivliostyle.config.js  

EPUBディレクトリ内に .git ディレクトリをはじめ、多くの必要のないファイルが入っています。(EPUB生成前に生成したPDFファイル tbf13-draft.pdf なども)
OPFファイル content.opf の内容を見ると、それらEPUBに必要のないファイルもすべて manifest 要素内のitem要素として出力されています。

EPUBに含めるのは、EPUBに必要なリソースだけにするべきではないでしょうか?

@MurakamiShinyu
Copy link
Member

Typo in #418 (comment): "pub-manfiest" → "pub-manifest"

@MurakamiShinyu
Copy link
Member

このPRのテスト中に気がついたEPUBプレビューでの問題:

@MurakamiShinyu
Copy link
Member

MurakamiShinyu commented Jul 17, 2023

configのtoc: trueによる目次の生成で、目次の内容が文字化けした異常なものになるケースがあります。

テストサンプル
https://github.com/MurakamiShinyu/kaigainotabi1

これをgit cloneして、vivliostyle.config.jsに toc: true の設定を加えてEPUB生成をテストしました。

$ ../vivliostyle-cli/dist/cli.js build -o /tmp/kaigainotabi1_toc_true.epub
⊙ Collecting build config
../../../../tmp/kaigainotabi1_toc_true.epub has been created.
🎉 Built successfully.

$ ../vivliostyle-cli/dist/cli.js preview /tmp/kaigainotabi1_toc_true.epub
🚀 Up and running ([ctrl+c] to quit)

スクリーンショット
スクリーンショット 2023-07-17 12 23 39

生成された index.xhtml の内容:

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops"><head>
    <title>海外�旅〔上〕</title>
    <link href="publication.json" rel="publication" type="application/ld+json" />
    <link href="theme/theme.css" rel="stylesheet" />
  </head>
  <body>
    <h1>海外�旅〔上〕</h1>
    <nav id="toc" role="doc-toc" epub:type="toc">
      <h2>Table of Contents</h2>
      <ol>
        <li><a href="text/index.xhtml">海外�旅〔上〕</a></li>
        <li><a href="text/chap01.xhtml">一�����ヨーロッパ�旅</a></li>
        <li><a href="text/chap02.xhtml">二�2回目�ヨーロッパ�旅</a></li>
        <li><a href="text/chap03.xhtml">三�カナダ�アメリカ�旅</a></li>
        <li>
          <a href="text/chap04.xhtml">四�タイ�ミャンマー�インド��旅</a>
        </li>
        <li><a href="text/chap05.xhtml">五��インド�スリランカ�旅</a></li>
        <li><a href="text/backmatter.xhtml">奥付</a></li>
      </ol>
    </nav>
  

<nav epub:type="landmarks" id="landmarks" hidden=""><ol><li><a epub:type="toc" href="index.xhtml#toc">Table of Contents</a></li></ol></nav></body></html>

toc.ncx の内容のテキストも同様に文字化け。

@MurakamiShinyu
Copy link
Member

# Supports remote HTML file (linked resources will be downloaded)
vivliostyle build https://vivliostyle.github.io/vivliostyle_doc/samples/gon/index.html -o output.epub

この例をテストしてみました。

$ ./dist/cli.js build https://vivliostyle.github.io/vivliostyle_doc/samples/gon/index.html -o /tmp/gon.epub
◡ Fetching remote contents
../../../../tmp/gon.epub has been created.
🎉 Built successfully.

EPUBができました。この内容を確認します:

$ unzip /tmp/gon.epub -d /tmp/gon_epub/
Archive:  /tmp/gon.epub
 extracting: /tmp/gon_epub/mimetype  
 extracting: /tmp/gon_epub/META-INF/container.xml  
 extracting: /tmp/gon_epub/EPUB/content.opf  
 extracting: /tmp/gon_epub/EPUB/publication.json  
 extracting: /tmp/gon_epub/EPUB/toc.ncx  
   creating: /tmp/gon_epub/EPUB/vivliostyle_doc/
   creating: /tmp/gon_epub/EPUB/vivliostyle_doc/samples/
   creating: /tmp/gon_epub/EPUB/vivliostyle_doc/samples/gon/
   creating: /tmp/gon_epub/EPUB/vivliostyle_doc/samples/gon/img/
 extracting: /tmp/gon_epub/EPUB/vivliostyle_doc/samples/gon/img/gon.jpg  
 extracting: /tmp/gon_epub/EPUB/vivliostyle_doc/samples/gon/index.xhtml  
 extracting: /tmp/gon_epub/EPUB/vivliostyle_doc/samples/gon/style.css  

publication.json ファイルが含まれているのが気になります。この内容を見ると、readingOrder が次のように指定されてます:

  "readingOrder": [
    {
      "url": "vivliostyle_doc/samples/gon/index.html"
    }
  ],

しかし、このファイル "vivliostyle_doc/samples/gon/index.html" はEPUB内に含まれていません。EPUB内にあるのはXHTMLに変換されて拡張子が .xhtml になったものです。その index.xhtml ファイルを見ると、次のように publication.json ファイルへのリンクがあります:

<link rel="publication" type="application/ld+json" href="../../../publication.json" />

前のコメント #418 (comment) の繰り返しになりますが、publication.json のようなEPUBに不要なファイルは含まれないようにして、XHTMLファイルにもpublication.jsonへのリンクを入れないようにするべきだと思います。

@MurakamiShinyu
Copy link
Member

MurakamiShinyu commented Jul 17, 2023

# Supports single-doucment publication
vivliostyle build https://www.w3.org/TR/wpub/ -o output.epub

この例をテストすると、次のようにエラーになってEPUBは生成できません:

$ ./dist/cli.js build https://www.w3.org/TR/wpub/ -o /tmp/wpub.epub
⚠ Publication manifest validation failed. Processing continues, but some problems may occur.
REQUIRED must have required property 'conformsTo'

> 1 | {
    | ^ ☹️  conformsTo is missing here!
  2 |   "@context": [
  3 |     "https://schema.org",
  4 |     "https://www.w3.org/ns/wp-context"
◠ Fetching remote contents

このエラーの理由は次のようです:

https://www.w3.org/TR/wpub/ のHTMLには次のように publication manifest が含まれている:

    <link rel="publication" href="#wp_manifest" />
    <script type="application/ld+json" id="wp_manifest">{
    "@context": [
        "https://schema.org",
        "https://www.w3.org/ns/wp-context"
    ],

この publication manifest は、この2019年のW3Cノート Web Publications (W3C Working Group Note 13 August 2019) の時点で定義されていたもので、そのあと2020年に勧告になった Publication Manifest (W3C Recommendation 10 November 2020) ではpublication manifest仕様が少し変わって conformsTo プロパティがMUSTとなっている。
Vivliostyle CLIでの publication manifest の validation は2020年のPublication Manifest仕様のものなので、2019年のW3Cノートに含まれるpublication manifestでは合っていないのでエラーになる。

(なお、Vivliostyle.jsの問題で https://www.w3.org/TR/wpub/ をViewerでロード中にエラーが発生してました。これについては vivliostyle/vivliostyle.js#1209 で修正済み。)


このwpubのW3Cノートは特殊なケースなので、「Supports single-doucment publication」の例に使うのは別のものにしたほうがよいかと思います。そこでW3C仕様で別の例を試したところ:

$ ./dist/cli.js build https://www.w3.org/TR/pub-manifest/ -o /tmp/pub-manifest.epub
◡ Fetching remote contents

EPUBが生成されずに終了します。次も同様:

$ ./dist/cli.js build https://www.w3.org/TR/css-2023/ -o /tmp/css-2023.epub
◡ Fetching remote contents

@spring-raining
Copy link
Member Author

@MurakamiShinyu 詳細なレビューありがとうございます。

EPUBに含めるのは、EPUBに必要なリソースだけにするべきではないでしょうか?

まずはこちらの問題について対応する予定です。現在の includeAssets configのように、webpubやEPUBを出力するときに含めるファイルを制限するようにしてみます。

https://vivliostyle.github.io/vivliostyle_doc/samples/gon/index.html のテスト時に "vivliostyle_doc/samples/gon/index.html" がEPUB内に含まれておらず、XHTMLに変換されて拡張子が .xhtml になったものがある

出力されるEPUBのcontent.opfの内容は以下のように拡張子がXHTMLに変換されたものになっています。publication.jsonの内容はEPUBリーダーからは無視されるため、EPUBファイルとしては問題なく読み込める形式になっています。

  <manifest>
    <item id="vivliostyle_docsamplesgonindexxhtml" href="vivliostyle_doc/samples/gon/index.xhtml" media-type="application/xhtml+xml" properties="nav"></item>
    ...
  </manifest>
  <spine toc="tocncx">
    <itemref idref="vivliostyle_docsamplesgonindexxhtml"></itemref>
  </spine>

ただ、確かに不要なpublication.jsonがあることで紛らわしくなっています。上記の対応で、publication.jsonもEPUBに含めないようにします。

https://www.w3.org/TR/wpub/ のテスト時にエラーが発生する

こちらはサンプルが良くなかったです。vivliostyle-cliが準拠しているPublication Manifestのドキュメントを指定すると、エラーが表示されずに正しくEPUBが出力されます。
ちなみに、 https://www.w3.org/TR/wpub/ を指定した際に ⚠ Publication manifest validation failed. Processing continues, but some problems may occur. というエラー (警告) が表示されていますが、処理自体が続行しているのでこの警告が出た後もEPUBで保存できているはずです。

https://www.w3.org/TR/pub-manifest/ https://www.w3.org/TR/css-2023/ のEPUBが生成されずに終了してしまう

すみません、こちらは私の環境では問題が再現できていません。より詳細な再現状況を教えてもらえますか? もしくは、dependencyの再インストールと再ビルド (yarn install && yarn build) で修正されるかもしれません。

@MurakamiShinyu
Copy link
Member

MurakamiShinyu commented Jul 19, 2023

…処理自体が続行しているのでこの警告が出た後もEPUBで保存できているはずです。

https://www.w3.org/TR/pub-manifest/ https://www.w3.org/TR/css-2023/ のEPUBが生成されずに終了してしまう

すみません、こちらは私の環境では問題が再現できていません。より詳細な再現状況を教えてもらえますか?

私の環境では、いずれもEPUBが生成されずに終了してしまいます。
環境によるのかと調べたところ、私のMac mini M1で、arm64の環境だとこの問題があり、x86_64 の環境だと問題が起きません。Windows 10 (x64)環境でも問題が起きません。いずれの環境でもNodeバージョンを18と20とで切り替えて試しましたが、Nodeバージョンは関係ないようです。

この問題が起きる環境で、VS Codeのデバッガで調べて以下のことが分かりました。

HTML内容のロード中に、"jsdomError" が発生して、例外が投げられて終了しています。次のところ:

virtualConsole.on('jsdomError', (error) => {
// Most of CSS using Paged media will be failed to run CSS parser of JSDOM.
// We just ignore it because we don't use CSS parse results.
// https://github.com/jsdom/jsdom/blob/a39e0ec4ce9a8806692d986a7ed0cd565ec7498a/lib/jsdom/living/helpers/stylesheets.js#L33-L44
// see also: https://github.com/jsdom/jsdom/issues/2005
if (error.message === 'Could not parse CSS stylesheet') {
return;
}
throw new DetailError(
'Error occurred when loading HTML',
error.stack ?? error.message,
);
});

このときの "jsdomError" の error の内容は以下です:

error の内容:

Error: Could not load img: "https://www.w3.org/StyleSheets/TR/2016/logos/W3C"
    at onErrorWrapped (/Users/shinyu/viv/vivliostyle-cli/node_modules/jsdom/lib/jsdom/browser/resources/per-document-resource-loader.js:38:19)
    at onLoadWrapped (/Users/shinyu/viv/vivliostyle-cli/node_modules/jsdom/lib/jsdom/browser/resources/per-document-resource-loader.js:65:16)
    at Object.check (/Users/shinyu/viv/vivliostyle-cli/node_modules/jsdom/lib/jsdom/browser/resources/resource-queue.js:76:23)
    at /Users/shinyu/viv/vivliostyle-cli/node_modules/jsdom/lib/jsdom/browser/resources/resource-queue.js:119:14
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {type: 'resource loading', detail: Error: Error: node-canvas was built without SV…
    at onLoadImage (/Users/shinyu/viv/vivli…, stack: 'Error: Could not load img: "https://www.w3.or…ions (node:internal/process/task_queues:95:5)', message: 'Could not load img: "https://www.w3.org/StyleSheets/TR/2016/logos/W3C"'}

error.detail の内容:

Error: Error: node-canvas was built without SVG support
    at onLoadImage (/Users/shinyu/viv/vivliostyle-cli/node_modules/jsdom/lib/jsdom/living/nodes/HTMLImageElement-impl.js:111:17)
    at onLoadWrapped (/Users/shinyu/viv/vivliostyle-cli/node_modules/jsdom/lib/jsdom/browser/resources/per-document-resource-loader.js:53:33)
    at Object.check (/Users/shinyu/viv/vivliostyle-cli/node_modules/jsdom/lib/jsdom/browser/resources/resource-queue.js:76:23)
    at /Users/shinyu/viv/vivliostyle-cli/node_modules/jsdom/lib/jsdom/browser/resources/resource-queue.js:119:14
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {stack: 'Error: Error: node-canvas was built without S…ions (node:internal/process/task_queues:95:5)', message: 'Error: node-canvas was built without SVG support'}

つまり、SVG画像 https://www.w3.org/StyleSheets/TR/2016/logos/W3C が "Error: node-canvas was built without SVG support" のためにロードできずにエラーになっています。W3C文書にはW3Cロゴを表示するため、このSVG画像を埋め込むimg要素 <img alt="W3C" width="72" height="48" src="https://www.w3.org/StyleSheets/TR/2016/logos/W3C"> があり、この問題が起きます。

単純化したHTMLファイルでもテストしてみました。

私のMacのarm64環境の場合のテスト結果:

mac-arm64-result

x86_64環境の場合のテスト結果:

mac-x86_64-result

このように、SVG画像を参照するimg要素がある場合、arm64環境ではEPUBが生成されず、x86_64環境では正常にEPUBが生成されます。

SVG画像の内容が壊れている場合は、いずれの環境でもEPUBが生成されません。何のエラーメッセージも出ないのでこれも問題があると思います。

存在しないファイルを参照するimg要素がある場合、いずれの環境でもEPUBが生成されません。このケースでは "Failed to fetch webbook resources:" とエラーメッセージが出ます。

ためしに、上記 "jsdomError" のエラーの処理のところで、例外を投げないでそのままた return するようにしたところ、どのテストでもEPUBが生成されるようになりました。存在しないファイルを参照するimg要素がある場合でも "Failed to fetch webbook resources:" とエラーメッセージが出るけれども、EPUBは生成されます。
動作としてはこのようになるべきでないかと思います。

arm64環境でだけ "Error: node-canvas was built without SVG support" となるのは、node-canvas の次の問題のようです:

@spring-raining
Copy link
Member Author

詳細な調査ありがとうございます。ARM64でnode-canvasが使えないのは問題ですね…解決方法を探してみます

@spring-raining
Copy link
Member Author

@MurakamiShinyu 以下の修正が完了しました。

  • 不要なファイルをEPUBに含めないよう修正
  • 特定の環境でwebpubから参照されるSVGがダウンロードできない問題を修正
  • 生成された目次のドキュメントが文字化けする問題を修正

なお、

test-broken-svg-img.html - SVG画像を参照するimg要素がある。ただしSVG画像の内容が壊れている

こちらのドキュメントについては、引き続きエラーメッセージが出ずに終了してしまう問題があります。これは、参照しているライブラリ (Skia) で破損したSVGファイルを読み込もうとしたときにsegfaultが発生することが原因で、すぐの対応が難しそうです。発生条件もそれほど高くなさそうなので、一旦既知の問題としてそのままリリースする予定です。

@MurakamiShinyu
Copy link
Member

@spring-raining 修正確認しました。

質問です。
src/processor/html.ts の virtualConsole.on('jsdomError', (error) => {…}) で、CSSについては例外を投げないように次のようになってます:

  if (error.message === 'Could not parse CSS stylesheet') {
    return;
  }

SVGに限らずimgに対しても例外を投げないように、

  if (error.message.startsWith('Could not load img:')) {
    return;
  }

などとするのではだめだったのでしょうか? そうしないでJSDOMをforkして、node-canvasを別のものにした理由は何でしょう?

@MurakamiShinyu
Copy link
Member

EPUB・WebPubの生成のとき、コマンドラインで --title を指定すると次の警告メッセージが出るのは何か間違ってるようです:

--title flag seems to be set but the current export setting doesn't support this. This option will be ignored.

例:
テストサンプル https://raw.githack.com/vivliostyle/vivliostyle.js/master/packages/core/test/files/svg_properties.html
(このHTMLにはtitle要素がない)
まず、--title オプションなしで実行すると:

$ ./dist/cli.js build https://raw.githack.com/vivliostyle/vivliostyle.js/master/packages/core/test/files/svg_properties.html -o /tmp/output.epub
✖ Error: EPUB must have a title of one or more characters
    at exportEpub (file:///Users/shinyu/viv/vivliostyle-cli/dist/output/epub.js:181:15)
    at async build (file:///Users/shinyu/viv/vivliostyle-cli/dist/build.js:130:21)

titleがないとエラーになる。そこで --title を指定すると:

$ ./dist/cli.js build https://raw.githack.com/vivliostyle/vivliostyle.js/master/packages/core/test/files/svg_properties.html -o /tmp/output.epub --title "SVG Properties Test"
◡ Collecting build config

--title flag seems to be set but the current export setting doesn't support this. This option will be ignored.
◡ Fetching remote contents
../../../../tmp/output.epub has been created.
🎉 Built successfully.

生成されたEPUBを見ると、指定したタイトル "SVG Properties Test" がOPFファイルに入っているので、

--title flag seems to be set but the current export setting doesn't support this. This option will be ignored.

が出るのは単に間違いのようです。
WebPub出力でも同様です。

@spring-raining
Copy link
Member Author

JSDOMをforkして、node-canvasを別のものにした理由は何でしょう?

node-canvas を置き換えた @napi-rs/canvas は、node-canvas とは異なり各アーキテクチャ向けに事前にビルドされたバイナリを提供しているため、今回のようにインストール時の環境によりSVGの読み込みに失敗する問題は回避できます。
単に virtualConsole.on('jsdomError', (error) => {…}) でエラーを無視するようにした場合、エラーの出力自体は抑制できても実際にSVGファイルをダウンロードできているかが分からなくなるため、エラーが回避可能であれば今回のように極力回避した上でエラー発生時は明示的に失敗させるのが良い方針かと思います。

Copy link
Member

@MurakamiShinyu MurakamiShinyu left a comment

Choose a reason for hiding this comment

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

👍

@spring-raining spring-raining merged commit ba2e7f7 into main Jul 24, 2023
@spring-raining spring-raining deleted the epub branch July 24, 2023 08:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

EPUB output support
2 participants