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: Support adding sections for generated ToC documents #484

Open
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

spring-raining
Copy link
Member

@spring-raining spring-raining commented Apr 22, 2024

resolve #254

Add a new toc.sectionDepth option that enables to add section heading titles to table of contents documents.

Show section heading titles of <h1> - <h4>

vivliostyle.config.js:

export default {
  toc: {
    title: 'Table of Contents',
    htmlPath: 'index.html',
    sectionDepth: 4,
  },
  ...
};

Customize transform function that renders ToC documents

Each transform function should return the Element type of hast format.

vivliostyle.config.js:

import { h } from 'hastcript';

export default {
  toc: {
    sectionDepth: 6,
    transformSectionList: (nodeList) => (propsList) =>
      h('div', nodeList.map(({href, headingText}, i) =>
        h('div', [h('a', {href}, headingText), propsList[i].children])
      )),
  },
  ...
};

@spring-raining spring-raining self-assigned this Apr 22, 2024
@spring-raining spring-raining marked this pull request as ready for review April 29, 2024 11:49
title: entry.title || upath.basename(entry.target, '.html'),
href: encodeURI(upath.relative(distDir, entry.target)),
sections,
children: [], // TODO
Copy link
Member Author

Choose a reason for hiding this comment

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

This option is reserved for future updates.

@MurakamiShinyu
Copy link
Member

EPUB出力とwebpub出力をテストしたところ問題がありました。

EPUB出力

ディレクトリ examples/table-of-contents/

$ ../../dist/cli.js build -o /tmp/output.epub
◠ Collecting build config
../../../../../../tmp/output.epub has been created.
🎉 Built successfully.

これで /tmp/output.epub が生成されます。しかし、このEPUBをEPUBCheckでテストすると、たくさんのエラーが出ます。

ERROR (RSC-020) at "output.epub/EPUB/content.opf" (行数 13, 桁数 136):
"manuscript/01_Computing Paradigms.xhtml" は有効なURLではありません (Illegal character in path segment: space is not allowed)

ERROR (RSC-020) at "output.epub/EPUB/content.opf" (行数 14, 桁数 156):
"manuscript/02_Algorithm Design and Analysis.xhtml" は有効なURLではありません (Illegal character in path segment: space is not allowed)

ERROR (RSC-020) at "output.epub/EPUB/content.opf" (行数 15, 桁数 146):
"manuscript/03_Systems and Architecture.xhtml" は有効なURLではありません (Illegal character in path segment: space is not allowed)

ERROR (RSC-005) at "output.epub/EPUB/content.opf" (行数 19, 桁数 14):
ファイル解析時のエラー: 要素 "itemref" に必要な属性が書かれていません. "idref"

ERROR (RSC-005) at "output.epub/EPUB/content.opf" (行数 20, 桁数 14):
ファイル解析時のエラー: 要素 "itemref" に必要な属性が書かれていません. "idref"

ERROR (RSC-005) at "output.epub/EPUB/content.opf" (行数 21, 桁数 14):
ファイル解析時のエラー: 要素 "itemref" に必要な属性が書かれていません. "idref"

など。EPUBを解凍してcontent.opfファイルを見てみると、

    <item id="manuscript01_computing-paradigmsxhtml" href="manuscript/01_Computing Paradigms.xhtml" media-type="application/xhtml+xml"></item>
    <item id="manuscript02_algorithm-design-and-analysisxhtml" href="manuscript/02_Algorithm Design and Analysis.xhtml" media-type="application/xhtml+xml"></item>
    <item id="manuscript03_systems-and-architecturexhtml" href="manuscript/03_Systems and Architecture.xhtml" media-type="application/xhtml+xml"></item>

のように、URLにエスケープされていないスペースが入っていたり、

  <spine>
    <itemref idref="indexxhtml"></itemref>
    <itemref></itemref>
    <itemref></itemref>
    <itemref></itemref>
  </spine>

のように、idref 属性のない<itemref>要素があります。

webpub出力

ディレクトリ examples/table-of-contents/

$ ../../dist/cli.js build -o /tmp/webpub
◠ Collecting build config
../../../../../../tmp/webpub has been created.
🎉 Built successfully.

出力された /tmp/webpub/publication.json を見てみると

  "readingOrder": [
    {
      "url": "index.html",
      "name": "Table of Contents",
      "rel": "contents",
      "type": "LinkedResource"
    },
    {
      "url": "manuscript/01_Computing%20Paradigms.html",
      "name": "Computing Paradigms"
    },
    {
      "url": "manuscript/02_Algorithm%20Design%20and%20Analysis.html",
      "name": "Algorithm Design and Analysis"
    },
    {
      "url": "manuscript/03_Systems%20and%20Architecture.html",
      "name": "Systems and Architecture"
    }
  ],
  "resources": [
    "image.png",
    "manuscript/01_Computing Paradigms.html",
    "manuscript/02_Algorithm Design and Analysis.html",
    "manuscript/03_Systems and Architecture.html",
    "publication.json"
  ],

"resources" に、"readingOrder" に出力されているHTMLファイル名が重複して出力されています。そして、それらのファイル名に含まれるスペースがエスケープされていません。

それから、"resources" に "publication.json" があるのも間違いだと思います。

@MurakamiShinyu
Copy link
Member

文書titleとh1見出しに関して

VFMでは文書titleをfrontmatterで指定しないと最初の見出しがtitleになるので、たとえばMDファイルが次のようにレベル1の見出しではじまる場合、

# Computing Paradigms

## Introduction to Computational Thinking

生成される目次は次のようになります:

      <ol>
        <li>
          <a href="manuscript/01_Computing%20Paradigms.html"
            >Computing Paradigms</a
          >
          <ol>
            <li data-section-level="1">
              <a
                href="manuscript/01_Computing%20Paradigms.html#computing-paradigms"
                >Computing Paradigms</a
              >
              <ol>
                <li data-section-level="2">
                  <a
                    href="manuscript/01_Computing%20Paradigms.html#introduction-to-computational-thinking"
                    >Introduction to Computational Thinking</a
                  >

いくつか問題があります。

文書titleとその文書の最初のh1見出しが同じでも重複して目次に出る

1. Computing Paradigms
   1. Computing Paradigms

のように、同じタイトルが目次に出ます。

"examples/table-of-contents/manuscript/01_Computing Paradigms.md" で、frontmatterでtitleを記述して、最初のレベル1見出しをsectionを生成しない # Computing Paradigms # の形式にしているのは、この問題を避けるためだと思います。しかし、それでも以下が気になっています:

section要素内の見出しだけを目次項目にするのでよいかどうか

HTML仕様のHeading content では

Heading content defines the heading of a section (whether explicitly marked up using sectioning content elements, or implied by the heading content itself).

とあります。つまりHeading contentの要素(h1-h6)は明示的にsectioning contentの要素(article, aside, nav, section)がなくても暗黙的なセクションの見出しとなるということです。この論理からすると、明示的なsection要素の有無によって目次の項目とするかどうかを決めるのはあまり適切でないかもしれません。

また、HTML仕様のsectioning contentには、section要素だけでなく、article、aside、nav要素もあります。これらの要素にある見出しも目次項目にしたい場合があるかと思います。たとえば、複数の記事(article)をまとめた出版物では各記事の見出しを目次項目にする必要があります。

section等の要素とは無関係に見出し要素h1-h6を目次項目にするほうがよいかもしれません。しかし、引用ブロック(blockquote)内の見出しは除外する必要があります。
Pandocの --toc--toc-depth オプション https://pandoc.org/MANUAL.html#option--toc-depth を試してみると、そのようになってました。

見出しを目次項目にする場合には文書のtitleは使わないでよいのでは

たいていの場合、文書の最初のh1見出しはその文書(章など)のタイトルです。HTMLのtitle要素よりもそのh1要素を見出し項目にするほうが、次の利点があります:

  • h1要素ならばルビなどインラインの要素を含むことができるが、title要素はテキストのみ

sectionDepth の指定がないか0のときだけ、文書のtitleを使って1以上の値の指定があるときは見出し要素を使うようにするとよいかもしれません。

preview中に文書titleを変更しても目次項目に反映されない不具合

preview中に文書title(MDファイルのfrontmatterのtitle、またはfrontmatterなしの場合は最初の見出し)を変更しても目次に反映されません。たとえば、 "examples/table-of-contents/manuscript/01_Computing Paradigms.md" のfrontmatterの title: Computing Paradigms の内容を書き換えても、preview中の目次には変更が反映されません。

@MurakamiShinyu
Copy link
Member

見出しのルビ要素などインライン要素が目次項目に反映されない

見出しから目次項目を生成するとき、見出しに含まれるルビ要素などインライン要素が反映されず、テキストのみが使われるようです。たとえば見出し内の <ruby>漢字<rt>かんじ</rt></ruby> が目次項目では "漢字かんじ" になってしまいます。これでは使えません。ルビ要素などインライン要素が目次項目に反映される必要があります。

@spring-raining
Copy link
Member Author

EPUB出力

webpub出力

こちらはこのPRに関係なくすでにある問題のようなので、別のPRで修正します。

preview中に文書titleを変更しても目次項目に反映されない不具合

見出しのルビ要素などインライン要素が目次項目に反映されない

こちらの問題は修正しました。 6cc5a51 2fd1190

@spring-raining
Copy link
Member Author

section要素内の見出しだけを目次項目にするのでよいかどうか

見出しを目次項目にする場合には文書のtitleは使わないでよいのでは

個人的にはメリットだけでなくデメリットもある仕様だと思うので、この部分はもう少し意見を募りたいです。

@spring-raining
Copy link
Member Author

section要素内の見出しだけを目次項目にするのでよいかどうか

以下の条件のとき、タイトルを目次項目とせずにセクションの見出しをその文章の目次項目とするように仕様を変更しました。 d427d46

  • sectionDepth が1以上
  • 文章のトップレベルの見出し付きセクションが1つのみで、その見出しの要素が <h1> である

一方で、見出し要素を全て目次項目として列挙する動作は議論の余地があると思います。現実のHTMLでは本来のHeading contentの用途以外で <h1> - <h6> が使われることも多く、見出し要素のみで暗黙的にSectioning contentがあると仮定するのは、実際に目次を生成する際に制御が難しくなると感じました。

HTML仕様のsectioning contentには、section要素だけでなく、article、aside、nav要素もあります。

この意見をもとに、<section> <article> <aside> <nav> 要素の見出しを目次項目とする仕様が良いように思います。

@MurakamiShinyu
Copy link
Member

hgroup要素の扱い

hgroup要素 で目次がどうなるかテストしました。

"examples/table-of-contents/manuscript/01_Computing Paradigms.md" に次のsectionを追加してpreview

<section>
<hgroup>
<p>p in hgroup</p>
<h2>H2</h2>
</hgroup>
<p>Paragraph</p>
</section>

その結果は、生成された目次にhgroup要素の内容の要素が次のようにコピーされました。

            <li>
              <span>
                <p>p in hgroup</p>
                <h2>H2</h2>
              </span>
            </li>

preview結果のスクリーンショット:

Screenshot 2024-05-01 16 24 25

@MurakamiShinyu
Copy link
Member

section要素内の見出しだけを目次項目にするのでよいかどうか

以下の条件のとき、タイトルを目次項目とせずにセクションの見出しをその文章の目次項目とするように仕様を変更しました。 d427d46

  • sectionDepth が1以上
  • 文章のトップレベルの見出し付きセクションが1つのみで、その見出しの要素が <h1> である

body要素の直下のh1なども同様にするべきでしょう。

一方で、見出し要素を全て目次項目として列挙する動作は議論の余地があると思います。現実のHTMLでは本来のHeading contentの用途以外で <h1> - <h6> が使われることも多く、見出し要素のみで暗黙的にSectioning contentがあると仮定するのは、実際に目次を生成する際に制御が難しくなると感じました。

「現実のHTMLでは本来のHeading contentの用途以外で <h1> - <h6> が使われることも多く」というのはどういう場合ですか?
考えられるのは、何らかのブロック(コード、リスト、引用、図表など)にタイトルを付ける場合です。そのような場合に見出し要素が使われることがあるとしても、目次項目にしたいセクション見出しのレベルとは別のものを使うものでないでしょうか?
(たとえば、h1-h3をセクション見出しとして目次項目にしたい場合、h4-h6を目次項目に出さない見出しに使うなど。)

逆に、目次項目をsection(あるいはsectioning content)内の最初の要素である見出しに制限することは、次のような標準的なHTML文書内の見出しが除外される問題があります:

<body>
  <main>
    <h1>Document Title</h1>
    <section>
      <header>
        <h2>Section Title</h2>
        <p>Paragraph in Header</p>
      </header>
      <p>Paragraph in Section</p>

main要素内のh1要素はトップレベルにあるh1と同様に文書のトップレベルにの見出しとして扱われるべきだし、header要素内の見出しはheader要素が属するsectionの見出しとして扱われるべきだと思います。

目次の生成は基本的にHTML仕様の Headings and outlines に従うのがよいと思います。 "The outline is all headings in a document, in tree order." です。この all headings というのを sectionDepth で制限するだけでよいと思います。

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.

自動生成される目次に、原稿中の見出しを含めてほしい
2 participants