Giter Club home page Giter Club logo

swift-doc's Introduction

swift-doc

CI

A package for generating documentation for Swift projects.

Given a directory of Swift files, swift-doc generates HTML or CommonMark (Markdown) files for each class, structure, enumeration, and protocol as well as top-level type aliases, functions, and variables.

Example Output

Requirements

Command-Line Utility

swift-doc can be used from the command-line on macOS and Linux.

Installation

Homebrew

Run the following command to install using Homebrew:

$ brew install swiftdocorg/formulae/swift-doc

If you already have swift-doc installed, run the following command to upgrade your installation:

$ brew upgrade swift-doc

If installing or upgrading fails with the message Error: Failed to download resource "swift-doc", try resetting your installation with the following commands:

$ brew uninstall swift-doc
$ brew untap swiftdocorg/formulae
$ brew install swiftdocorg/formulae/swift-doc

Docker

You can run swift-doc from the latest Docker image with the following commands:

$ docker pull swiftdoc/swift-doc:latest
$ docker run -it swiftdoc/swift-doc

Manually

Run the following commands to build and install manually:

$ git clone https://github.com/SwiftDocOrg/swift-doc
$ cd swift-doc
$ make install

If you're on Ubuntu Linux, you may need to first install the prerequisites by running the following command:

$ apt-get update
$ apt-get install -y libxml2-dev graphviz

Usage

OVERVIEW: A utility for generating documentation for Swift code.

USAGE: swift doc <subcommand>

OPTIONS:
  --version               Show the version.
  -h, --help              Show help information.

SUBCOMMANDS:
  generate                Generates Swift documentation
  coverage                Generates documentation coverage statistics for Swift
                          files
  diagram                 Generates diagram of Swift symbol relationships

Note: The swift driver provides extensibility through subcommands. If you type an unknown subcommand like swift foo, the system looks for a command called swift-foo in your PATH. This mechanism allows swift-doc to be run either directly or as swift doc.

swift-doc generate

OVERVIEW: Generates Swift documentation

USAGE: swift doc generate [<inputs> ...] --module-name <module-name> [--output <output>] [--format <format>] [--base-url <base-url>]

ARGUMENTS:
  <inputs>                One or more paths to a directory containing Swift files. 

OPTIONS:
  -n, --module-name <module-name>
                          The name of the module 
  -o, --output <output>   The path for generated output (default:
                          .build/documentation)
  -f, --format <format>   The output format (default: commonmark)
  --base-url <base-url>   The base URL used for all relative URLs in generated
                          documents. (default: /)
  --minimum-access-level <minimum-access-level>
                          The minimum access level of the symbols which should
                          be included. (default: public)
  -h, --help              Show help information.

The generate subcommand takes one or more paths and enumerates them recursively, collecting all Swift files into a single "module" and generating documentation accordingly. Any hidden directories are skipped, including .git and other directories with paths starting with a dot (.). Top-level Tests directories are skipped as well.

$ swift doc generate path/to/SwiftProject --module-name SwiftProject
$ tree .build/documentation
$ documentation/
├── Home
├── (...)
├── _Footer.md
└── _Sidebar.md

By default, output files are written to .build/documentation in CommonMark / GitHub Wiki format, but you can change that with the --output and --format option flags.

$ swift doc generate path/to/SwiftProject/Sources --module-name SwiftProject --output Documentation --format html
$ Documentation/
├── (...)
└── index.html

By default, swift-doc includes only symbols declared as public or open in the generated documentation. To include internal or private declarations, pass the --minimum-access-level flag with the specified access level.

swift-doc coverage

OVERVIEW: Generates documentation coverage statistics for Swift files

USAGE: swift doc coverage [<inputs> ...] [--output <output>]

ARGUMENTS:
  <inputs>                One or more paths to a directory containing Swift files.

OPTIONS:
  -o, --output <output>   The path for generated report 
  --minimum-access-level <minimum-access-level>
                          The minimum access level of the symbols which should
                          be included. (default: public)
  -h, --help              Show help information.

The coverage subcommand generates documentation coverage statistics for Swift files.

$ git clone https://github.com/SwiftDocOrg/SwiftSemantics.git

$ swift run swift-doc coverage SwiftSemantics/Sources --output "dcov.json"
$ cat dcov.json | jq ".data.totals"
{
  "count": 207,
  "documented": 199,
  "percent": 96.1352657004831
}

$ cat dcov.json | jq ".data.symbols[] | select(.documented == false)"
{
  "file": "SwiftSemantics/Supporting Types/GenericRequirement.swift",
  "line": 67,
  "column": 6,
  "name": "GenericRequirement.init?(_:)",
  "type": "Initializer",
  "documented": false
}
...

While there are plenty of tools for assessing test coverage for code, we weren't able to find anything analogous for documentation coverage. To this end, we've contrived a simple JSON format inspired by llvm-cov.

If you know of an existing standard that you think might be better suited for this purpose, please reach out by opening an Issue!

swift-doc diagram

OVERVIEW: Generates diagram of Swift symbol relationships

USAGE: swift doc diagram [<inputs> ...]

ARGUMENTS:
  <inputs>                One or more paths to a directory containing Swift files.

OPTIONS:
  --minimum-access-level <minimum-access-level>
                          The minimum access level of the symbols which should
                          be included. (default: public)
  -h, --help              Show help information.

The diagram subcommand generates a graph of APIs in DOT format that can be rendered by GraphViz into a diagram.

$ swift run swift-doc diagram Alamofire/Source > Alamofire.gv
$ head Alamofire.gv
digraph Anonymous {
  "Session" [shape=box];
  "NetworkReachabilityManager" [shape=box];
  "URLEncodedFormEncoder" [shape=box,peripheries=2];
  "ServerTrustManager" [shape=box];
  "MultipartFormData" [shape=box];

  subgraph cluster_Request {
    "DataRequest" [shape=box];
    "Request" [shape=box];

$ dot -T svg Alamofire.gv > Alamofire.svg

Here's an excerpt of the graph generated for Alamofire:

Excerpt of swift-doc-api Diagram for Alamofire

GitHub Action

This repository also hosts a GitHub Action that you can incorporate into your project's workflow.

The CommonMark files generated by swift-doc are formatted for publication to your project's GitHub Wiki, which you can do with github-wiki-publish-action. Alternatively, you could specify HTML format to publish documentation to GitHub Pages or bundle them into a release artifact.

Inputs

  • inputs: A path to a directory containing Swift (.swift) files in your workspace. (Default: "./Sources")
  • format: The output format ("commonmark" or "html") (Default: "commonmark")
  • module-name: The name of the module.
  • base-url: The base URL for all relative URLs generated in documents. (Default: "/")
  • output: The path for generated output. (Default: "./.build/documentation")

Example Workflow

# .github/workflows/documentation.yml
name: Documentation

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v1
      - name: Generate Documentation
        uses: SwiftDocOrg/swift-doc@master
        with:
          inputs: "Sources"
          module-name: MyLibrary
          output: "Documentation"
      - name: Upload Documentation to Wiki
        uses: SwiftDocOrg/github-wiki-publish-action@v1
        with:
          path: "Documentation"
        env:
          GH_PERSONAL_ACCESS_TOKEN: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}

Development

Web Assets

CSS assets used by the HTML output format are processed and generated by PostCSS. To make changes to these assets, you'll need to have Node.js and a package manager, such as npm, installed on your machine.

Navigate to the .node directory and run npm install to download the required tools and libraries.

$ cd .node
$ npm install

Note: package.json is located at a hidden .node subdirectory to prevent Xcode from displaying or indexing the contents of node_modules when opening the main project.

From the .node directory, run the watch script to start watching for changes to files in the Assets folder. Whenever an asset source file is added, removed, or updated, its corresponding (unoptimized) product is automatically generated in the Sources/swift-doc/Generated folder.

$ npm run watch

When you're happy with the results, commit any changes to the source files in Assets as well as the generated files in Sources/swift-doc/Generated.

$ git add Assets Sources/swift-doc/Generated
$ git commit

Release Process

The following information is primarily for the benefit of project maintainers. That said, if you have any suggestions for how to improve this process, please let us know by opening an issue.

Follow these steps to release a new version of swift-doc:

  • Verify that the latest commit passed all CI checks.
  • Update the Changelog by creating a new heading for the release and modifying the last path component for the unreleased link reference.
  • Update the version constant in the command-line executable.
  • Create a new commit with the message "Bump version to $VERSION", where $VERSION is a SemVer-compatible version number.
  • Tag that commit with the tag name "$VERSION"
  • Run the command git push origin master --tags
  • Create a new release that corresponds to the new tag.

Known Issues

  • Xcode cannot run unit tests (U) when opening the swift-doc package directly, as opposed first to generating an Xcode project file with swift package generate-xcodeproj. (The reported error is: Library not loaded: @rpath/lib_InternalSwiftSyntaxParser.dylib). As a workaround, you can install the latest toolchain and enable it in "Xcode > Preferences > Components > Toolchains". Alternatively, you can run unit tests from the command line with swift test.

License

MIT

Contact

Mattt (@mattt)

swift-doc's People

Contributors

andrewchang-bird avatar angelostavrow avatar apollozhu avatar compnerd avatar dependabot[bot] avatar dinsen avatar heckj avatar heeaad avatar jaapwijnen avatar kaishin avatar kean avatar lukas-stuehrk avatar mattkiazyk avatar mattpolzin avatar mattt avatar maxdesiatov avatar mbrandonw avatar morqon avatar niw avatar rastersize avatar samsymons avatar tunous avatar victor-pavlychko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swift-doc's Issues

swift-doc fails when encountering a directory that is named like a Swift source file

Hello! First, swift-doc looks like it could be a really useful tool so thank you!

I attempted to run swift-doc with a project I am working on that relies on MapboxGeocoder and I ran into a weird scenario where swift-doc returns an error of

Error: Error Domain=NSCocoaErrorDomain Code=257 "The file “MapboxGeocoder.swift” couldn’t be opened because you don’t have permission to view it."

The problem seems to be that MapboxGeocoder, when installed via Cocoapods, creates a directory in /Pods named MapboxGeocoder.swift which swift-doc then tries to read as a Swift source file because it looks like a Swift source file if you just look at the name. Removing MapboxGeocoder from the project I am working on though and then running swift-doc works as expected!

I don't know how common of a problem this is, figured I would at least pass it along as something that I ran into when getting started with trying out swift-doc.

Generate different documentation per platform

As an author of the frameworks which work on multiple platforms and have slightly different APIs for each one, I would like to be able to generate different sets of documentation for each platform and allow users to select which one they want to see.

As an alternative, it could be the same documentation, but it should clearly indicate which APIs are available on which platforms.

Rearchitect documentation generators

One of the consequences of #65 is that we now have an option that applies to HTML output, but not CommonMark. This kind of divergence isn't unexpected — certainly, as we expand functionality to support additional output formats like DocSets (#27), it was inevitable.

We're at the point now where the original assumptions we made to ship the initial proof-of-concept are starting to break down, and it'd be great to find a solution that will set us up for success in version 1.x and beyond.

Here's what I'm looking for in a solution, in order of importance:

  1. Something that lets us add support for new formats, without encroaching on or breaking the existing ones.
  2. The ability to test generated output without actually running the swift-doc command (a full integration test should be run separately), as discussed in #62
  3. The ability for users to use a 3rd-party generator without forking swift-doc itself — for extensibility, but also some flexibility for us about what's included in the main offering.

...so basically, a plugin system. 😭

So far, the only solution I've been able to come up with that meets all three of these criteria is to make each format its own subcommand of generate. For example, running:

$ swift doc generate html

...would look for an executable named swift-doc-generate-html. This is the same approach that allows swift-doc to be executed as a subcommand of swift, and would let anyone write and/or install their own custom output format.

Does anyone else have any other ideas about what we should do?

Path-relative URLs are not working when deployed to GitHub Pages

Hi, I deployed the documentation generated by swift-doc to GitHub pages. There is an issue with path-relative URLs. For example, if you got to ImageProcessing page and click of any of the URLs there, e.g. ImageProcessors.Resize, it shows 404 page.

I'm using the latest swift-doc from master:

commit 0b2291a52f22a30d5e2528f06be79d40cac570cb (HEAD -> master, origin/master, origin/HEAD)
Merge: e5c4b85 0ac5744
Author: Mattt <[email protected]>
Date:   Sun Apr 5 08:15:44 2020 -0700

    Merge pull request #53 from SwiftDocOrg/mattt/operator-fix
    
    Fix logic error when classifying operators in generate subcommand

Implement Service Workers for offline access

The Service Worker API allows webpages to download, install, and activate resources that can later be used by the browser. This allows users to view webpages when they're not connected to the Internet or the server hosting the original webpage is offline. Typically, things like cache invalidation and state restoration present significant challenges to adoption, but we fortunately don't have to deal with those for static content like documentation.

Using the GitHub Action fails to build because libxml2 can't be found

I attempted to use the GitHub Action and it fails to build as it seems it cannot find libxml2. My yaml file is mostly copied from the readme as such:

 name: documentation

 on: 
   push:
     branches:
       - master

 jobs:

   documentation:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v1
       - name: Generate Documentation
         uses: SwiftDocOrg/swift-doc@master
         with:
           inputs: "Source"
           output: "Documentation"
       - name: Upload Documentation to Wiki
         uses: SwiftDocOrg/github-wiki-publish-action@v1
         with:
           path: "Documentation"
         env:
           GH_PERSONAL_ACCESS_TOKEN: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}

with the following error:

2020-04-02T10:51:17.1999611Z �[91mwarning: you may be able to install libxml-2.0 using your system-packager:
2020-04-02T10:51:17.1999887Z     apt-get install libxml2-dev
2020-04-02T10:51:17.1999968Z 
2020-04-02T10:51:17.3529060Z �[0m[1/22] Compiling cmark xml.c
2020-04-02T10:51:19.3766648Z [2/23] Compiling cmark utf8.c
2020-04-02T10:51:20.9528071Z [3/24] Compiling HypertextLiteral Swift+HyperTextConvertible.swift
2020-04-02T10:51:39.8014675Z [4/25] Compiling GraphViz Attribute.swift
2020-04-02T10:51:40.1024297Z [5/26] Compiling DOM Comment.swift
2020-04-02T10:51:40.1026381Z <module-includes>:1:10: note: in file included from <module-includes>:1:
2020-04-02T10:51:40.1026549Z #include "libxml2-markup.h"
2020-04-02T10:51:40.1027053Z          ^
2020-04-02T10:51:40.1027215Z /swiftdoc/.build/checkouts/Markup/Modules/libxml2-markup.h:3:9: error: 'libxml2/libxml/tree.h' file not found
2020-04-02T10:51:40.1027441Z #import <libxml2/libxml/tree.h>
2020-04-02T10:51:40.1027583Z         ^
2020-04-02T10:51:40.1027730Z /swiftdoc/.build/checkouts/Markup/Sources/DOM/Comment.swift:1:8: error: could not build C module 'libxml2'
2020-04-02T10:51:40.1027943Z import libxml2
2020-04-02T10:51:40.1028086Z        ^
2020-04-02T10:51:40.1145904Z Makefile:17: recipe for target 'swift-doc' failed
2020-04-02T10:51:40.1146156Z �[91mmake: *** [swift-doc] Error 1
2020-04-02T10:51:40.6684447Z The command '/bin/sh -c make install prefix=/build' returned a non-zero code: 2
2020-04-02T10:51:40.6693539Z �[0m
2020-04-02T10:51:40.6811173Z ##[error]Docker build failed with exit code 2

I have attached the full log of that step of the workflow run: 2_Build [email protected], but as it's an open source project, you can see the results for yourself on the repo.

Refactor and optimize HTML generation

Here be dragons 🐲

In an effort to get everything out the door, I kind of took a "whatever works" approach to development. To that end, HyperTextLiteral was great for getting out of the way. But it's obvious that we're leaving a lot of performance wins on the table with our current implementation.

<div class="discussion">
\#(documentation.discussionParts.compactMap { part -> HypertextLiteral.HTML? in
if let part = part as? SwiftMarkup.Documentation.Callout {
return Callout(part).html
} else if let part = part as? String {
if part.starts(with: "```"),
let codeBlock = (try? CommonMark.Document(part))?.children.compactMap({ $0 as? CodeBlock }).first,
(codeBlock.fenceInfo ?? "") == "" ||
codeBlock.fenceInfo?.compare("swift", options: .caseInsensitive) == .orderedSame,
let source = codeBlock.literal
{
var html = try! SwiftSyntaxHighlighter.highlight(source: source, using: Xcode.self)
html = linkCodeElements(of: html, for: symbol, in: module)
return HTML(html)
} else {
var html = (try! CommonMark.Document(part)).render(format: .html, options: [.unsafe])
html = linkCodeElements(of: html, for: symbol, in: module)
return HTML(html)
}
} else {
return nil
}
})
</div>
"""# as HypertextLiteral.HTML)

Once the design stabilizes, it'd be nice to take another pass over all of this to clean and speed things up.

Sub-Tasks

  • Extract repeated markup patterns into components (e.g. definition lists of symbols)
  • Create helper functions for things like string parameterization (`"Foo Bar" -> "foo-bar")

File names like cancelRequest(for/).md are not recognized by Jekyll

I'm trying to feed the Markdown files generated by swift-doc to Jekyll and it is not happy about certain file names.

~> bundle exec jekyll serve
Configuration file: /Users/kean/Develop/kean.github.io/_config.yml
            Source: /Users/kean/Develop/kean.github.io
       Destination: /Users/kean/Develop/kean.github.io/_site
 Incremental build: disabled. Enable with --incremental
      Generating... 
jekyll 3.8.5 | Error:  Invalid scheme format: cancelRequest(for

The name of the file in question is cancelRequest(for/).md. It was produced for a global function.

Private in documentation

Hi!
first off, thanks for this tool, it's really awesome so far!
I have just come across one issue - I am not sure if it is a bug or a known limitation - but if I generate the documentation, it also creates a documentation for private methods (if they appear in public class).
When I looked through the source code, it really does seem that there is filter for types, but not their properties themselves.

For example:
This function is private but it appears in the generated documentation

SwiftDoc should inherit delegate and superclass docs.

It would be great if SwiftDoc's generated docs could inherit the inline documentation for protocol implementations and overrides. For example, Alamofire has a SessionDelegate type which implements the various URLSession*Delegate protocol methods we're interested in. In Xcode, those methods inherit the documentation from the protocol itself. For example:

Screen Shot 2020-04-01 at 9 14 56 PM

SwiftDoc currently generates only the method declarations.

"File name too long" errors when saving Alamofire docs as HTML

Just tried running this on Alamofire.

swift doc generate Source --output swiftdoc --format html --module-name Alamofire

(The --module-name requirement isn't documented, so perhaps the docs need to be updated?)

The command generates some HTML but also prints many lines of "Error Domain=NSPOSIXErrorDomain Code=13 "Permission denied" and then prints a final error:

Error: Error Domain=NSCocoaErrorDomain Code=514 "The item couldn’t be saved because the file name “DataResponseSerializerProtocol_DownloadResponseSerializerProtocol_ResponseSerializer_DataPreprocessor_PassthroughPreprocessor_GoogleXSSIPreprocessor_ResponseSerializer_DownloadResponseSerializerProtocol_DataRequest_DownloadRequest_DataRequest_DataResponseSerializer_DownloadRequest_StringResponseSerializer” is invalid." UserInfo={NSFilePath=/Users/user/Desktop/Code/Alamofire/swiftdoc/DataResponseSerializerProtocol_DownloadResponseSerializerProtocol_ResponseSerializer_DataPreprocessor_PassthroughPreprocessor_GoogleXSSIPreprocessor_ResponseSerializer_DownloadResponseSerializerProtocol_DataRequest_DownloadRequest_DataRequest_DataResponseSerializer_DownloadRequest_StringResponseSerializer, NSUnderlyingError=0x7ff552cf9f70 {Error Domain=NSPOSIXErrorDomain Code=63 "File name too long"}}

I know there are a lot of types in the file, but that's a heck of a file name. 😆

Allow parameters to be specified through configuration file

As we begin to add (#65) and consider (#57, #72) new options for the generate command, I think it's likely that the number of options for the generate command will soon exceed what can be reasonably expressed through command-line arguments alone.

Maybe this isn't inevitable. If we took seriously the canon of parsimony in our API design, perhaps we'd find that a small, fixed set of parameters are all that are necessary. This could all be a trap, a slippery slope that projects fall into all too frequently in a rush to add functionality. I'd love to be hear better arguments about limiting feature creep.

But from where I am right now, it's hard to look at, say, the configuration options for jazzy or other comparable tools and think that we'll find a way to solve the same problem without a similar number of settings. Taken altogether in aggregate, you start to get the sense about the inherent complexity of the problem.

So, assuming this is indeed something we'll need, it's probably something we should figure out before 1.0.0. Here's what I'm thinking:

  • Extend ArgumentParser to make options Codable. Unless this already exists, this is something that would be useful beyond swift-doc and a good candidate for an upstream patch or separate library.
  • By default, look for a .swift-doc.json (spelling?) file and read those as a base configuration, and add an option for where to look for a configuration file.
  • Options in the configuration file override the default values. Any options passed from the command line to the executable override ones from a configuration file (similar to how most systems work, including UserDefaults).
  • We should also think about versioning and validation for these files, as well as documentation.

html support

Spent the day attempting to add HTML support using [HTMLKit](https://github.com/vapor-community/HTMLKit

Very rudimentary html page created from the top level symbols

fork is: https://github.com/thecb4/swift-doc.git

If you think it's worth it, I can keep going.

<!DOCTYPE html>
<html>
	<head>
		<title>Swift Documentation</title>
		<meta property='og:title' content='Swift Documentation'>
			<meta name='twitter:title' content='Swift Documentation'>
				<meta name='author' content='thebc4'>
					<meta name='twitter:creator' content='_thecb4'>
						<meta name='viewport' content='width=device-width, initial-scale=1.0'>
							<link rel='stylesheet' href='https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css' type='text/css'>
							</head>
							<body>
								<nav class='navbar navbar-light bg-light'>
									<span class='navbar-brand mb-0 h1'>swift-doc</span>
								</nav>
								<div class='p-3'>
									<div class='row'>
										<div class='col-2'>
											<div class='nav flex-column nav-pills' id='v-pills-tab' role='tablist' aria-orientation='vertical'>
												<a class='nav-link active' id='v-pills-Generic-tab' data-toggle='pill' href='#v-pills-Generic' role='tab' aria-controls='v-pills-Generic' aria-selected='false'>Generic</a>
												<a class='nav-link' id='v-pills-Type-tab' data-toggle='pill' href='#v-pills-Type' role='tab' aria-controls='v-pills-Type' aria-selected='false'>Type</a>
												<a class='nav-link' id='v-pills-Contextual-tab' data-toggle='pill' href='#v-pills-Contextual' role='tab' aria-controls='v-pills-Contextual' aria-selected='false'>Contextual</a>
												<a class='nav-link' id='v-pills-SourceFile-tab' data-toggle='pill' href='#v-pills-SourceFile' role='tab' aria-controls='v-pills-SourceFile' aria-selected='false'>SourceFile</a>
												<a class='nav-link' id='v-pills-Unknown-tab' data-toggle='pill' href='#v-pills-Unknown' role='tab' aria-controls='v-pills-Unknown' aria-selected='false'>Unknown</a>
												<a class='nav-link' id='v-pills-Relationship-tab' data-toggle='pill' href='#v-pills-Relationship' role='tab' aria-controls='v-pills-Relationship' aria-selected='false'>Relationship</a>
												<a class='nav-link' id='v-pills-Predicate-tab' data-toggle='pill' href='#v-pills-Predicate' role='tab' aria-controls='v-pills-Predicate' aria-selected='false'>Predicate</a>
												<a class='nav-link' id='v-pills-API-tab' data-toggle='pill' href='#v-pills-API' role='tab' aria-controls='v-pills-API' aria-selected='false'>API</a>
												<a class='nav-link' id='v-pills-CompilationCondition-tab' data-toggle='pill' href='#v-pills-CompilationCondition' role='tab' aria-controls='v-pills-CompilationCondition' aria-selected='false'>CompilationCondition</a>
												<a class='nav-link' id='v-pills-Module-tab' data-toggle='pill' href='#v-pills-Module' role='tab' aria-controls='v-pills-Module' aria-selected='false'>Module</a>
												<a class='nav-link' id='v-pills-Identifier-tab' data-toggle='pill' href='#v-pills-Identifier' role='tab' aria-controls='v-pills-Identifier' aria-selected='false'>Identifier</a>
												<a class='nav-link' id='v-pills-Symbol-tab' data-toggle='pill' href='#v-pills-Symbol' role='tab' aria-controls='v-pills-Symbol' aria-selected='false'>Symbol</a>
												<a class='nav-link' id='v-pills-Component-tab' data-toggle='pill' href='#v-pills-Component' role='tab' aria-controls='v-pills-Component' aria-selected='false'>Component</a>
											</div>
										</div>
										<div class='col-10'>
											<div class='tab-content' id='v-pills-tabContent'>
												<div class='tab-pane fade show active' id='v-pills-Generic' role='tabpanel' aria-labelledby='v-pills-Generic-tab'>
													<h2>Generic</h2>
												</div>
												<div class='tab-pane fade' id='v-pills-Type' role='tabpanel' aria-labelledby='v-pills-Type-tab'>
													<h2>Type</h2>
												</div>
												<div class='tab-pane fade' id='v-pills-Contextual' role='tabpanel' aria-labelledby='v-pills-Contextual-tab'>
													<h2>Contextual</h2>
												</div>
												<div class='tab-pane fade' id='v-pills-SourceFile' role='tabpanel' aria-labelledby='v-pills-SourceFile-tab'>
													<h2>SourceFile</h2>
												</div>
												<div class='tab-pane fade' id='v-pills-Unknown' role='tabpanel' aria-labelledby='v-pills-Unknown-tab'>
													<h2>Unknown</h2>
												</div>
												<div class='tab-pane fade' id='v-pills-Relationship' role='tabpanel' aria-labelledby='v-pills-Relationship-tab'>
													<h2>Relationship</h2>
												</div>
												<div class='tab-pane fade' id='v-pills-Predicate' role='tabpanel' aria-labelledby='v-pills-Predicate-tab'>
													<h2>Predicate</h2>
												</div>
												<div class='tab-pane fade' id='v-pills-API' role='tabpanel' aria-labelledby='v-pills-API-tab'>
													<h2>API</h2>
												</div>
												<div class='tab-pane fade' id='v-pills-CompilationCondition' role='tabpanel' aria-labelledby='v-pills-CompilationCondition-tab'>
													<h2>CompilationCondition</h2>
												</div>
												<div class='tab-pane fade' id='v-pills-Module' role='tabpanel' aria-labelledby='v-pills-Module-tab'>
													<h2>Module</h2>
												</div>
												<div class='tab-pane fade' id='v-pills-Identifier' role='tabpanel' aria-labelledby='v-pills-Identifier-tab'>
													<h2>Identifier</h2>
												</div>
												<div class='tab-pane fade' id='v-pills-Symbol' role='tabpanel' aria-labelledby='v-pills-Symbol-tab'>
													<h2>Symbol</h2>
												</div>
												<div class='tab-pane fade' id='v-pills-Component' role='tabpanel' aria-labelledby='v-pills-Component-tab'>
													<h2>Component</h2>
												</div>
											</div>
										</div>
									</div>
								</div>
								<footer class='footer fixed-bottom py-4 bg-dark text-white-50'>
									<div class='container text-center'>
										<small>Copyright &copy; swift-doc</small>
									</div>
								</footer>
								<script src='https://code.jquery.com/jquery-3.4.1.slim.min.js'></script>
								<script src='https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js'></script>
								<script src='https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js'></script>
							</body>
						</html>

Support Packages with Multiple Modules

Right now, swift-doc does a syntactic parse over any source files globbed from the input argument. With #31, it'll be much easier to sort things out and understand how symbols relate to one another.

Add option to generate subcommand for specifying which access levels are included

My original motivation for swift-doc was to generate documentation for libraries. However, as the tool gains wider adoption, teams will likely want to use it internally for their own apps. The major difference between libraries and apps is that apps are typically much less concerned about ACL (if all of your code is in a single app target, everything "just works").

Rather than force teams to change their code in a way that would otherwise provide no immediate benefit (i.e. sprinkling public throughout their code base), I think it would make sense to provide an option for internal declarations to be included in the generated output.

As far as how this should work:

  • The current behavior of only looking for public or open declarations should probably continue to be the default.
  • To help folks who might be confused about nothing happening when they run swift doc generate (#70), we should communicate something like "No public declarations found, set the (option) flag to...).
  • To accommodate future distinctions, this option should probably take an enumerated value rather than a Boolean. So --minimum-access-level internal instead of --include-internal-declarations.
  • And, of course, this should be documented. I think a "Getting Started" guide should be considered a P1 for our 1.0.0 release. (#73)

Unable to use in Xcode 11.4 on Catalina

I just installed swift-doc (for the first time) using

brew install swiftdocorg/formulae/swift-doc

I'm getting the following error when trying to generate any documentation :-

usern:$ swift doc Sources/ --output Documentation
Error: SwiftSyntax parser library isn't compatible
usern:$ 

I've running Catalina 10.15.4 and Xcode 11.4

Thanks!

Issues generating HTML documentation for Nuke

Hi Mattt, this looks absolutely fantastic and I would really like to start using swift-doc in my projects. I downloaded the latest swift-doc version from master (85b5872) and tried running it against Nuke's master.

swift doc generate ~/Develop/Nuke/Sources/ --output Documentation --format html --module-name Nuke

My command line tools are set to Xcode 11.4.

It seems it got a bit confused. I think it might be because of some of the "namespaces" and typealiases.

The actual types are named ImageProcessors.GaussianBlur, etc.

Screen Shot 2020-04-01 at 13 13 56

Documentation.zip

Provide option to incorporate directory of Markdown files into generated HTML documentation

As suggested by @MaxDesiatov in #57:

It would be great if there was an option not just to include README.md, but a given directory hierarchy of multiple markdown files that provide extended documentation: tutorials, guidelines, license, code of conduct etc.

Scoping the feature request a bit, I think a good first step would be to add a new, optional parameter to the generate command to specify a directory of Markdown files (Documentation by default) to be rendered alongside the generated symbol reference docs.

For example, given the following project structure:

.
├── Documentation
│   ├── Advanced-Usage.md
│   ├── FAQ.md
│   └── Getting-Started.md
└── Sources

swift doc generate --format html would produce three "Guide" pages for "Advanced Usage", "FAQ", and "Getting Started".

My only hesitation here is that it gets us into the business of static site generation more generally (a corollary of Zawinski's Law. To that end, I'm unsure on whether to should support any form of YAML front matter...

Edit: Actually, you know what? I'm putting my foot down: No YAML front matter! I know of a better way that doesn't add another dependency or threaten to go down a slippery slope of supporting TOML / JSON / whatever front matter — I randomly came across it in this Hugo issue thread:

@bep: This is just me thinking out loud during Christmas. I kind of like the simplicity of it. The idea is to use SGML Processing Instructions as a way to pass parameters to the new and shiny render hooks in Hugo (images and links).

So instead of this:

---
title: Getting Started
---

Reprehenderit culpa qui enim elit sunt laborum do occaecat nostrud exercitation enim ex...

You do something like this (final spelling TBD):

Reprehenderit culpa qui enim elit sunt laborum do occaecat nostrud exercitation enim ex...

<?swiftdoc title="Getting Started" ?>

Processing Instructions aren't rendered by default, and would be otherwise invisible. And unlike front matter, it can appear anywhere in the document.

If we scope this feature to Markdown files with optional PI for customization, I think that strikes a good balance for a "batteries included" output, with the option to further customize using a dedicated static site generator based on the CommonMark output.

documented only some pods

hey, it worked for me and generated this html file which is probably
documentation for some pods and third party libraries and can not find any of my classes (models, view , presenters) , i even searched for some code in the documentation and could not find it in my code

image

JSONEncoder.NonConformingFloatEncodingStrategy.convertToString error

Hi @mattt I'm always hitting this issue ?

How could I help fixing it ?

Error: invalidValue(-nan, Swift.EncodingError.Context(codingPath: [NestedCodingKeys(stringValue: "totals", intValue: nil), CodingKeys(stringValue: "percent", intValue: nil)], debugDescription: "Unable to encode Double.nan directly in JSON. Use JSONEncoder.NonConformingFloatEncodingStrategy.convertToString to specify how the value should be encoded.", underlyingError: nil))
make: *** [doc] Error 1

Thanks,

Incorporate README into generated HTML documentation

Most projects provide a helpful overview in their README, and it'd be nice to include that in the generated HTML documentation. This requires a new, optional parameter for the generate command (defaulting to README.md) and additional design work.

dyld: Library not loaded: @rpath/lib_InternalSwiftSyntaxParser.dylib

Environment

Xcode 11.4

Steps

  • Pull the latest swift-doc from master
  • Open Package.swift
  • Run swift-doc target or unit tests for SwiftDoc library

Observed result

dyld: Library not loaded: @rpath/lib_InternalSwiftSyntaxParser.dylib
Referenced from: /Users/kean/Library/Developer/Xcode/DerivedData/swift-doc-enlnpuwdeszizwbdykidcjodocbk/Build/Products/Debug/swift-doc
Reason: image not found

Related

realm/SwiftLint#3105

Add swift-doc version number to generated footers

The quick-and-dirty way to do this would be to hard-code a top-level version constant, but that would require a manual (and therefore error-prone) process of updating it for every release.

A better solution would be to pull this information from git during the build process (maybe using GYB?).

Even better would be if the Swift Package Manager had a way to generate these symbols at build time. Does anyone know if this is currently possible? And if not, what do you think about requesting this through Swift Evolution?

Add comparisons to similar tools to README

As mentioned in #39, the README used to have a "Motivation" section that discussed how swift-doc compared to Jazzy. I removed that for the first beta, because a lot of that information was no longer accurate or relevant. But we should definitely provide some similar guidance when this gets closer to a final release.

Use IndexStoreDB for Symbol Resolution

Currently, swift-doc builds a symbol graph syntactically. However, this approach has limitations (#25, #16). We may want to keep the current, syntactic approach around as an option for quick-and-dirty doc generation, but in the long-term, we'll likely want to leverage IndexStoreDB for this.

"Permission denied" error, documentation is still generated

Steps to reproduce?

  • Project: https://github.com/kaishin/Gifu
  • How I installed swift-doc: git clone then make install
  • Exact command: swift-doc generate ./Sources/ --module-name Gifu --output Documentation --format html

Expected behavior

  • HTML documentation generated at ./Documentation
  • No error output

Actual behavior

  • HTML documentation generated at ./Documentation
  • The following output
Error Domain=NSPOSIXErrorDomain Code=13 "Permission denied"
Error Domain=NSPOSIXErrorDomain Code=13 "Permission denied"

Environment

  • OS version: 10.15.4 (19E266)

Warning and Error during manual install

Xcode 11.4 on macOS 10.15.4

The README instructions for manual installation direct you to clone the swift-doc repo, cd into the folder, and run make install.

When I attempt make install, terminal displays a lot of "Cloning" and "Resolving" messages then a warning:
warning: failed to retrieve search paths with pkg-config; maybe pkg-config is not installed 'libxml2' libxml-2.0.pc: warning: couldn't find pc file

and then continues to work until it ends with this:

[45/45] Linking swift-doc install: chmod 755 /usr/local/bin: Operation not permitted install: /usr/local/bin/swift-doc: Permission denied make: *** [install] Error 71

Support for Objective-C?

Hi @mattt any plans for supporting Objective-C files? Would love to use this in a project that I am working on that is mainly written in Objective-C

SourceFile Symbol Producing Incorrect Name on Linux

When running the swift-doc GitHub action on Sources/SwiftDoc, the resulting documentation for SourceFile has the name "Contextual.Symbol.Extension.CompilationCondition.SourceFile".

Contextual.Symbol.Extension.CompilationCondition.SourceFile

Running this locally on macOS, I'm unable to reproduce this behavior.

This long name is a consequence of the SourceFile declaration following declarations relating to the Contextual protocol.

public protocol Contextual {}
extension Symbol: Contextual {}
extension Extension: Contextual {}
extension CompilationCondition: Contextual {}
// MARK: -
public struct SourceFile: Hashable, Codable {

This should be handled by visitPost, which pops the stack of contexts after visiting a contextual node:

mutating func visitPost(_ node: ExtensionDeclSyntax) {
assert(pop() is Extension)
}

However, these delegate methods don't appear to be called on Linux for some reason.

Warn and recover from errors when writing pages

As described in this tweet:

Is there a way to continue proceeding/skipping when some file errors. I am getting Domain=NSCocoaErrorDomain Code=514 "The item couldn’t be saved because the file name XYZ is invalid or too long?

This seems to be a result of #25, but we should also recover from these kinds of errors, emitting a warning to the console instead of exiting.

Strange results with extensions and types in same file.

Thanks this looks awesome! I did a quick test and I think I found some bugs.

I created a new Swift package and put the following in the source file:

/// Says hello
public func sayHello() {
    print("Hello!")
}

public extension NSNumber {
    /// Does this number represent a Bool
    public var isBool: Bool { return CFBooleanGetTypeID() == CFGetTypeID(self) }
}

public extension Result where Failure == Error {
    /// Converts a throwing block into a Result
    /// If any error is thrown a failure result is returned with the error. Otherwise success with the blocks return value.
    public static func of(_ block: () throws -> Success) -> Result<Success, Error> {
        do {
            return try .success(block())
        } catch {
            return .failure(error)
        }
    }
}

/**
 The default generated struct!
 */
struct spm_test {
    var text = "Hello, World!"
}

When I run the generator via swift doc generate Sources --module-name spm-test I get the following:

Home.md

# Types

  - [NSNumber.Result.spm\_test](NSNumber_Result_spm_test)

# Operators

  - [sayHello()](sayHello\(\))

NSNumber_Result_spm_test.md

# NSNumber.Result.spm\_test

The default generated struct\!

``` swift
struct spm_test
```

## Properties

## text

``` swift
var text = "Hello, World!"
```

sayHello().md

# sayHello()

## sayHello()

Says hello

``` swift
public func sayHello()
```

I think there are three bugs here:

  1. Notice how the spm_test struct is nested under the NSNumber and Result types.
  2. I don't get any docs for the public extensions.
  3. The top level sayHello function is documented as an operator.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.