📖

DocCを利用したチュートリアルの作り方と公開方法

2023/09/23に公開

概要

XcodeからDocCをチュートリアルを作成して、Web上で見れる状態にするまでについて、初見で気をつけたいポイントを含めて紹介します。
ただファイルやディレクトリの構成などは適時作成する際に作成者自身やチームで決めていただければと思いますのでここでは触れずにただ作成と公開についての内容となっています。

環境

この記事は以下のバージョン環境のもと作成されたものです。
【Xcode】14.3.1
【macOS】Ventuta

DocCとは

アプリ、フレームワーク、またはパッケージのドキュメントを作成したり、インタラクティブなチュートリアルを作成することができるツールです。
https://developer.apple.com/documentation/docc

アプリ、フレームワーク、またはパッケージ用の豊富なAPIリファレンスドキュメントとインタラクティブなチュートリアルを作成します。

また作成したドキュメントやチュートリアルはXcodeからビルドすることで見れたり、Webブラウザで見たりすることができます。

DocCで作れるもの

上記の通り主にAPIドキュメントとインタラクティブなチュートリアルを作成することができます。
APIドキュメントに関してはAppleが公開している以下のようなドキュメントと同じようなドキュメントを作成することができます。

本記事ではAPIドキュメントについて取り扱わないので、作成したい方は以下参考にして下さい。

https://developer.apple.com/documentation/docc/api-reference-syntax

インタラクティブなチュートリアルとは、ユーザーがアクティブに参加し、学習体験に直接関与するタイプのチュートリアルを指します。静的なテキストや画像だけでなく、具体的なタスクを通じてユーザーが新しいスキルや知識を獲得できるように設計されており、Appleが提供しているSwiftUIやUIKitのチュートリアル、またpointfreeによるTCAのチュートリアルなどが有名です。

https://developer.apple.com/tutorials/swiftui

https://pointfreeco.github.io/swift-composable-architecture/main/tutorials/meetcomposablearchitecture/

チュートリアルの作成方法

DocCででチュートリアルを作成する際に、何か特別なツールやフレームワークをDLやインストールする必要はなくXcodeさえあれば即既存のプロジェクトに組み込んだり、新規で作成したりすることができます。
今回は適当にプロジェクトを作りその中でチュートリアルを作成していきたいと思います。
作成手順は以下の通りです。
1. 目次を作る
2. チュートリアルのページを作る
3. 公開する

ただ作成する前に簡単に基本的に押さえておきたい知識があるので記載しておきます。
とりあえずさっさと作りたいという方はスキップして「チュートリアルを作る」から見てください。

予備知識

DocCでチュートリアルを作成する前に理解しておいた方がスムーズに作成できる知識が以下2点あります。
1. チュートリアルを作成する基本構成
2. チュートリアルを作成する基本知識

また公開に関しても2点あります。
1. GitHub Pages
2. docsの作成とディレクトリ

チュートリアルを作成する基本構成

チュートリアルを作成する上で押さえておきたい基本構成としてDocCを用いたチュートリアルので全体のファイル構成から見ていきます。だいたい作成するとこんな感じになります。

重要なのは.doccファイル配下でコードや画像ファイルなどのResources、目次やチュートリアルページとなる.tutorialを取り扱っているという部分です。

目次やチュートリアルページなどチュートリアル自体を構成する基本的なファイルは以下2種類です。

ファイル 詳細
Tutorial Table of Contents File 目次にあたるファイルです。
目次ファイル自体は一つでよく、目次ファイルの中で複数の目次を立てます。
Tutorial File チュートリアルページのファイルです。このファイルの中でインララクティブなチュートリアルを作成する事ができます。ただ表示したいCodeやImageはこのファイルで持たず、参照するだけのファイルなのでCodeやImageは別のディレクトリ(.docc/Resources配下)で管理します。

チュートリアルを作成する基本知識

チュートリアルはMarkdownで作成します。ディレクティブを使用して、導入部、セクション、ステップ、評価などの特定の種類のページと要素を定義します。
例えば下図の用に@Tutorial()のカッコ内にタイトルの文字列などを定義してチュートリアルのタイトルを定義することができます。

各要素に関しては以下を参照ください。
https://developer.apple.com/documentation/docc/tutorials
基本的な要素に関しては下記の「目次を作る」や「チュートリアルのページを作る」で紹介します。

チュートリアルを作る

ここからは実際に作成してみます。
フレームワークやパッケージ、新規、既存のプロジェクトファイル何でもいいので用意します。
ただ公開時にswift-docc-pluginを入れますのでSwift Packageで作成すると楽です。
ファイルを用意したら新規作成からDocumentationのセクションにある「Documentation Catalog」を選択し作成します。
Documentation Catalogにより.doccファイルがなぜ必要なのかは以下の通りです。

DocCではチュートリアルだけでなく、ドキュメントの作成も行えますが、以下のいずれかを含める際にはDocumentation Catalogが必要で、.doccファイル配下でそれぞれ定義する事になります。

  • フレームワークを紹介し、その最上位シンボルと、シンボルのプロパティとメソッドをカスタム構成する拡張ファイルを配置するランディング ページ。詳細については、「ドキュメント ページに構造を追加する」を参照してください。
  • ソース内のコメントを補足する拡張ファイルと、概念的な内容をサポートする記事。詳細については、「ドキュメント カタログへの補足コンテンツの追加」を参照してください。
  • ステップバイステップのインタラクティブなコンテンツを通じて開発者に API を教えるチュートリアル。詳細については、「対話型チュートリアルの構築」を参照してください。
  • 画像やビデオなど、ドキュメントで使用するリソース ファイル。

詳しくは以下参照ください。
https://developer.apple.com/documentation/xcode/documenting-apps-frameworks-and-packages#Configure-a-richer-documentation-experience

作成したら以下の画面の様なファイルが表示されます。

目次を作る

ここからチュートリアル作成の実装に入っていきます。
まずDocumentation.docc配下に目次を作成していきます。
新規作成からDocumentationのセクションにある「Tutorial Table of Contents File」を選択し目次ファイルを作成します。
作成したら以下の図の様なファイルが追加され、TableOfContents.tutorialには以下のようなCodeが定義されていると思います。

@Tutorials(name: "text") {
    @Intro(title: "text") {
        text
        
        @Image(source: file, alt: "accessible description")
    }
    
    @Chapter(name: "text") {
        text
        
        @Image(source: file, alt: "accessible description")
        
        @TutorialReference(tutorial: "doc:tutorial name")
    }
}

目次は@Tutorialsの中で作成します。
@Chapterの@TutorialReferenceでチュートリアルページのファイル名を定義する事で目次から書くチュートリアルページへ遷移する様に紐づけられます。
チュートリアルの進行順については現在(自分の知る限り)順序を指定するAPIとかはなく、上から順に進行していく形で生成されます。

ドキュメントのビルドは以下のどちらかの手順で行います。

  • 「Product」→「Build Documentation」
  • command + shift + control + D

ビルドが成功するとドキュメントが立ち上がり以下の用に表示されます。

※ビルド時に想定した通りに表示されない時は一度インデントずれが無いか確認してみてください。

Imageや.swiftなどのコードはResources配下で管理します。
以下は様々な文字の表示やImageを表示させたサンプルコードです。

@Tutorials(name: "Tutorial Title") {
    @Intro(title: "Intro") {
        # test
        ## test
        ### test
        
        test<br>test
        
        - test 1
        - test 2
        
        *test 3
        *test 4
        ** test 5 **
        *test 6*
        
        test 7
        
        test 8
        
        @Image(source: SampleImage, alt: "accessible description")
    }
    
    @Chapter(name: "text") {
        text
        
        @Image(source: file, alt: "accessible description")
        
        @TutorialReference(tutorial: "doc:tutorial name")
    }
}

上記を結果を見ると基本的にはmarkdownで書けている事が確認できますが<br>で改行することができず、自分が試した限りでは

text
//改行
text

のように改行を入れるもしくはスペース2個入れることでしか実装ができませんでした。

チュートリアルのページを作る

つづいてチュートリアルのページを作成します。
新規作成からDocumentationのセクションにある「Tutorial File」を選択し作成します。
作成した後は以下の様なファイル構成とCodeを確認する事ができると思います。

チュートリアルページと目次の関係を確認したい場合は先ほど作成したチュートリアルページを以下のように修正します。

@Tutorial(time: 30) {
    @Intro(title: "Tutorial01") {
        はじめてのチュートリアル作成
    }
    @Section(title: "section 1") {
        @ContentAndMedia {
            Imageとテキストで何か説明したい場合は`ContentAndMedia`を使用するよいい
            @Image(source: SampleImage, alt: "accessible description")
        }
        @Steps {
            @Step {
                デフォルトはこんなコード
                @Code(name: "TutorialCode01.swift", file: TutorialCode01.swift)
            }
            @Step {
                こんな感じで修正する
                @Code(name: "TutorialCode01-02.swift", file: TutorialCode01-02.swift)
            }
        }
    }
}

またResourcesに.swiftを二つほど追加します。

TutorialCode01
@Tutorial(time: number) {
    @Intro(title: "text") {
        text

        @Image(source: file, alt: "accessible description")
    }

    @Section(title: "text") {
        @ContentAndMedia {
            text

            @Image(source: file, alt: "accessible description")
        }

        @Steps {
            @Step {
                text

                @Image(source: file, alt: "accessible description")
            }

            @Step {
                text

                @Code(name: "display name", file: filename.swift)
            }
        }
    }
}
TutorialCode01-02
@Tutorial(time: 30) {
    @Intro(title: "Tutorial01") {
        はじめてのチュートリアル作成
    }

    @Section(title: "section 1") {
        @ContentAndMedia {
            Imageとテキストで何か説明したい場合は`ContentAndMedia`を使用するよいい

            @Image(source: SampleImage, alt: "accessible description")
        }

        @Steps {
            @Step {
                デフォルトはこんなコード

                @Code(name: "TutorialCode01.swift", file: TutorialCode01.swift)
            }

            @Step {
                こんな感じで修正する

                @Code(name: "TutorialCode01-02.swift", file: TutorialCode01-02.swift)
            }
        }
    }
}

最後に目次を修正します。

TableOfContents
@Tutorials(name: "Tutorial Title") {
    @Intro(title: "初めてのDocCでチュートリアル作成") {
        DocCでチュートリアルを作成する方法を紹介します。
    }
    
    @Chapter(name: "チュートリアルページの追加方法") {
        チュートリアルページの基本的な作成方法や追加方法について学べるチャプターです。
        @TutorialReference(tutorial: "doc:Tutorial01")
    }
}

これでチュートリアルページの作成と目次の関係を確認する事ができると思います。

codeに関しては同じStep内で同名を使用すると差分を自動で表示してくれます。
ただ少し注意も必要で、同じファイルを別のStepで使用すると最後に使用したStepでの表示名などが引き継がれて意図した表示にならないのでStep毎にcodeファイルは作成することをお勧めします。

@Step {
    hoge
    @Code(name: "Tutorial01.tutorial", file: Chapter02-03-01.swift)
}
@Step {
    ここで上のStepと同じファイルを参照し、表示名を`Tutorial02.tutorial`とした場合,
    上のStepでもファイルの表示名が`Tutorial02.tutorial`となる
    @Code(name: "Tutorial02.tutorial", file: Chapter02-03-01.swift)
}
↓解消する為にファイルを分ける
@Step {
    hoge
    @Code(name: "Tutorial01.tutorial", file: Chapter02-03-01.swift)
}
@Step {
    Chapter02-03-01.swiftとChapter02-03-02.swiftの中身が同じでもこれで別の名前、を表示させる事ができる
    @Code(name: "Tutorial02.tutorial", file: Chapter02-03-02.swift)
}
↓差分を表示させたい場合
@Step {
    hoge
    @Code(name: "Tutorial01.tutorial", file: Chapter02-03-01.swift)
}
@Step {
    参照ファイルは別にして表示名を同じにしておく必要がある
    @Code(name: "Tutorial01.tutorial", file: Chapter02-03-02.swift)
}

公開する

GitHubで適当なリポジトリを作成します。
(無料枠のアカウントで使用する場合はpublicにしておく必要があります)
続いて作成したリポジトリからSettings → PagesでGitHub Pagesの設定を行います。
Branchセクションでmain、/docsに変更してSaveします。

1時間〜2時間ぐらいでURLが発行されます。
GitHub Pagesを利用して静的ページを公開することに関して詳細を知りたい方は以下の参照ください。

https://docs.github.com/ja/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site

続いてswift-docc-pluginを入れていきます。
.doccを管理しているPackage.Swiftのdependenciesに以下のコードを追加します。

dependencies: [
    // Dependencies declare other packages that this package depends on.
    .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"),
],

Swift-DocC プラグインに関するドキュメントは以下の通りです。
https://apple.github.io/swift-docc-plugin/documentation/swiftdoccplugin/

続いてリポジトリをcloneしてSwift Packageファイルをリポジトリに移動さます。
移動させたらターミナルを開いてSwift Packageのルートから次のコマンドの
[path-to-docs-directory]
[target-name]
[hosting-base-path]
の部分を編集して実行します。

swift package --allow-writing-to-directory [path-to-docs-directory] \
    generate-documentation --target [target-name] \
    --disable-indexing \
    --transform-for-static-hosting \
    --hosting-base-path [hosting-base-path] \
    --output-path [path-to-docs-directory]

それぞれに関してはこちらに詳細が記載されていますのでご参照ください。

GitHub Pagesでサイトをホスティングする場合、そのサイトのURLのベースは通常、https://[username].github.io/[repository-name]/ という形になります。
ただ先ほどGitHub Pagesの設定で"main /docs"を選択して保存しましたので/docsディレクトリ下の内容が公開されることになります。
この設定の特性として、実際のURLから/docsが省略されて表示されます。
したがって、/docsディレクトリ以下のファイルやディレクトリは、URLから/docsを省略してアクセスすることができます。
URLをできる限り短縮した形で公開したい場合はリポジトリディレクトリ直下にdocsを作成した方が良いので[path-to-docs-directory]に関しては../docsなどすることをお勧めします。
ファイル構成として
リポジトリ/Swift Package/Package.swift
のような構成の場合swift package --allow-writing-to-directory...を実行するディレクトリはリポジトリ/Swift Package/で以下のようなコマンドになると思います。

swift package --allow-writing-to-directory ../docs \
    generate-documentation --target [ターゲット名] \
    --disable-indexing \
    --transform-for-static-hosting \
    --hosting-base-path [リポジトリ名] \
    --output-path ../docs

実行するとdocsファイルが生成されます。
生成後リポジトリにプッシュすると以下のURLでチュートリルを確認する事ができます。
https://[アカウント名].github.io/[リポジトリ名]/tutorials/[目次ファイル名]/
これで公開できたことを確認できます。

チュートリアル作成するチュートリアルを作成して公開しました

この記事を作成しながらチュートリアルを作成しましたが、どうせならこのまま公開してしまえということで「チュートリアルを作成する方法が学べる」チュートリアルを作成して公開しましたのでよければこちらもご覧ください。

https://oka-yuji.github.io/Tutorial/tutorials/tableofcontents/

参考記事

https://developer.apple.com/documentation/docc

Meet DocC documentation in Xcode
https://developer.apple.com/videos/play/wwdc2021/10166/

Host and automate your DocC documentation
https://developer.apple.com/videos/play/wwdc2021/10236

Zennの記事
https://zenn.dev/usamik26/books/swift-docc-xcode

Discussion