Giter VIP home page Giter VIP logo

quickdoc's Introduction

Quickdoc

API docs

See API.md.

Rationale

This library came out of the desire to have a fast and light weight tool that produces API docs from any Clojure code (.clj, .cljs, .cljc) without executing that code. This tool produces pure Markdown that you can read directly on Github and the output does not need CSS or JavaScript.

Quickdoc's properties:

Projects using quickdoc

Status

This project is just getting started. Therefore the API may still undergo significant changes based on early usage and feedback.

Babashka

task

Use as a babashka dependency and task:

# bb.edn
:tasks {
,,,
quickdoc {:doc "Invoke quickdoc"
          :extra-deps {io.github.borkdude/quickdoc {:git/sha "7c8bef54eda28367193ec433af01bb940114f012"}}
          :task (exec 'quickdoc.api/quickdoc)
          :exec-args {:git/branch "master"
                      :github/repo "https://github.com/clj-kondo/clj-kondo"
                      :source-paths ["src/clj_kondo/core.clj"]}}
,,,
}

Now you can run bb quickdoc and your API docs will be generated in API.md.

bbin

Install via bbin:

bbin install io.github.borkdude/quickdoc --as quickdoc

Clojure CLI

Add the following alias to your global or project-local deps.edn:

:aliases {
,,,
:quickdoc
{:deps {org.babashka/cli {:mvn/version "0.4.36"}
        io.github.borkdude/quickdoc
        {:deps/root "jvm"
         :git/sha "7c8bef54eda28367193ec433af01bb940114f012"}}
 :main-opts ["-m" "babashka.cli.exec" "quickdoc.api" "quickdoc"]}
,,,
}

Then you can call quickdoc using:

clj -M:quickdoc :github/repo https://github.com/clj-kondo :git/branch master

You can add default arguments to :exec-args in the alias:

:quickdoc
{,,,
 :exec-args {:github/repo "https://github.com/clj-kondo"
             :git/branch "master"}

So the command line invocation simply becomes:

clj -M:quickdoc

Clojure tool

Quickdoc is also available as a clj tool. Note that this way of invoking quickdoc is slower to start than with babashka.

To install, run:

clj -Ttools install io.github.borkdude/quickdoc '{:deps/root "jvm" :git/sha "<latest-sha>"}' :as quickdoc

Then invoke quickdoc using:

clj -Tquickdoc quickdoc '{:github/repo "https://github.com/borkdude/quickdoc"}'

Can it be improved to do ...?

Probably yes! Let me know in Github Discussions or create an issue.

License

See LICENSE.

quickdoc's People

Contributors

borkdude avatar eval avatar grahamcarlyle avatar helins avatar ikappaki avatar pedrorgirardi avatar rads 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

quickdoc's Issues

install via bbin

Would you be interested in a PR that documents how to install this via bbin? bbin settings in bb.edn also make installing more convenient.

Example of filename-fn for deps.edn

I saw examples of using filename-fn for a babashka task.

Could you provide an example of using filename-fn when used in a deps.edn file?
Use case is to append a sub-directory name in front of the link path that is generated.

Currently attempting the following in deps.edn

{...
 :paths ["src" "resources"]
 :aliases {:quickdoc ;; run using clj -M:quickdoc
           {:deps {org.babashka/cli {:mvn/version "0.4.38"}
                   io.github.borkdude/quickdoc
                   {:deps/root "jvm"
                    :git/sha "534c4d09ef052cd5e6896dad9ebe97dc01110264"}}
            :exec-args {:github/repo "https://github.com/{my-org}/{my-repo}"
                        :git/branch "main"
                        :filename-fn (fn [filename]
                                       (clojure.string/replace filename #"^/src" "{project}/src"))}
            :main-opts ["-m" "babashka.cli.exec" "quickdoc.api" "quickdoc"]}}}

but this results in the message Error building classpath. Error reading edn. No dispatch macro for: {path-to-deps.edn}

Is the filename-fn supposed to be defined in a clojure namespace?

Ability to customize source links

Hi there, we are evaluating quickdoc (against codox) for its speed and we are very happy with that so far.

One improvement we were thinking of was to add something generic for pointing to source (I see :github/repo is there but unfortunately we use DevOps).

The DevOps format for pointing to a file line is something like:

https://dev.azure.com/company/_git/project?path=/path/src/auth/jwt_test.clj&version=GBmain&_a=contents&line=18&lineEnd=19&lineStartColumn=1&lineEndColumn=1&lineStyle=plain

(it's cool that it has the ability to point to a column but we never really use that)

What do you think about that?

Should it be a template like in codox?

Tests

We really need some tests!

the doc generator creates some strange text from time to time.

I've run the document generator as follows.

clj -M:quickdoc :github/repo https://github.com/jimka2001/heavybool :git/branch main

One example of strange documentation is on the macro +and.
The text created is the following

Function.

Logical AND of heavy-bools which evaluates to a heavy-bool.
  Expands to code which evaluates to the left-most heavy-bool value
  in the argument list, otherwise evaluates to the right-most
  value.  If the argument list is empty, evaluates explicitly to
  +true

The text created for the function +annotate is the following which DOES NOT start with the
word Function.


Eg. `(+annotate hb :x x :y y)`
  to add `{:x x :y y}` as annotation on the given heavy-bool

What does the text Function. mean? 1) +and is a macro, not a normal function. And 2) +annotate is a regular function, but omits the Function. annotation.

No reader function for tag

Hi ! I'm trying to add alias :quickdoc in my deps.edn which contains a tagged literal, #env for clojure cli cuz I'm using this https://github.com/liquidz/build.edn/blob/a4a8f70d2df7591fd0eb7c455d7310f60600b8ac/doc/deploy.adoc#environmental-variables

However, it occurs an error No reader function for tag env. It'd be helpful to accept any literal tag in deps.edn or wanna expect an workaround.

If you give me an idea to work out, I want to contribute it as well.

Thank you for the quickdoc too!

Improve rendering performance

Hi there again, this is an issue that is only tangential to quickdoc - the fact that it produces a big .md does not work great for projects with a lot of namespaces as the problem is that any Markdown renderer would slow to a crawl when opening it.

Possible solutions:

  • Ability to include/exclude namespaces
  • Ability to associate namespaces with output files (landing page is the toc that will point to them)

I am ok with a "won't fix" answer given the project goals ๐Ÿ˜„

Any other nice bb-friendly suggestion for bigger projects?

GitHub rendering does not respect case-sensitive anchor tag names

If you have a namespace with both Db (a protocol) and db (a function), the generated table of contents as GitHub renders it will incorrectly link both entries to the same db section due to the collision.

Inspecting GitHub's HTML shows that a case-insensitive naming scheming is applied e.g. user-content-db (for Db) and user-content-db-1 (for db), which perhaps hints at an approach to fixing this.

This is definitely not super important but I figured it was worth capturing ๐Ÿ™‚

Quickdoc ignores arglists metadata

Checked on latest hash, minimal example:

(defn foo "docstring" {:arglists '([{:keys [x y z]}])} [opts] (println opts))

Glad to keep finding uses for this tool :)

Add option to leverage runtime info

This would be handy for e.g. babashka and/or joyride itself, so we can see what is inside the SCI context and create docstrings from that. With this we could generate docs for the entire SCI environment.

I got this idea when I saw PEZ updating docs manually for joyride.

Escape HTML entities within Markdown backticks

The current behavior outputs incorrect HTML and causes some Markdown renderers to break.

Input:

(defn script-tag "Returns a `<script>` tag." [])

Current output:

Returns a <code><script></code> tag.

Expected output:

Returns a <code>&lt;script&gt;</code> tag.

toc descriptions can be incomplete sentences

quickdock might generate incomplete sentences for the toc descriptions.

e.g. the babashka.process/sh generated entry below is an incomplete sentence

Table of contents

  • babashka.process - Shell out in Clojure with simplicity and ease.
    • $ - Convenience macro around process
    • *defaults* - Dynamic var containing overridable default options
    • check - Takes a process, waits until is finished and throws if exit code is non-zero.
    • destroy - Takes process or map
    • destroy-tree - Same as destroy but also destroys all descendants
    • exec - Replaces the current process image with the process image specified
    • pb - Returns a process builder (as record).
    • pipeline - Returns the processes for one pipe created with -> or creates
    • process - Takes a command (vector of strings or objects that will be turned
    • sh - Convenience function similar to clojure.java.shell/sh that sets
    • shell - Convenience function around process that was originally in babashka.tasks.
    • start - Takes a process builder, calls start and returns a process (as record).
    • tokenize - Tokenize string to list of individual space separated arguments.

This is because the description looks only at the first line of the dosctring. A possible solution could be to extract the text up to the first full stop, thus sh's toc description would become

Convenience function similar to `clojure.java.shell/sh` that sets `:out` and `:err` to `:string` by default and blocks.

Quickdoc a single file with a Markdown string as output

Thank you @borkdude for this project - it's another very useful tool! ๐Ÿ™

I was thinking of integrating Quickdoc on Pep, and one way that I intend to use Quickdoc is to give me a quick view of the namespace - it's almost like a "reader" view of the source code.

For that particular use case, I would expect to pass a filename to Quickdoc and it gives me back a Markdown string.

I'm not sure that makes sense, nor if people would use it like that, though.

strange link creation in md file

When I defined a function (macro in this case) as follows, I get strongly rendered md output.

(defmacro +and
  "Logical AND of heavy-bools which evaluates to a `heavy-bool`.
  Expands to code which evaluates to the left-most `heavy-bool` value
  in the argument list, otherwise evaluates to the right-most
  value.  If the argument list is empty, evaluates explicitly to
  `+true`"
  [& rest]
  (case (count rest)
    (0) +true
    (1) (first rest)
    (let [v (gensym)
          [head & tail] rest]
      `(let [~v ~head]
         (+if ~v
              (+and ~@tail)
              ~v)))))

screenshot_2024-07-04_at_11 48 45_720

I'm tagging a commit of my git repository which demonstrates the problem.
https://github.com/jimka2001/heavybool/blob/quickdoc-issue-39/clojure/API.md#and

Traceback when executing via clj

$ clj --version
Clojure CLI version 1.10.3.986
$ clj -Ttools install io.github.borkdude/quickdoc '{:deps/root "jvm" :git/tag "v0.2.3"}' :as quickdoc
Checking out: https://github.com/borkdude/quickdoc.git at 6c6cf25f016d40c5e3a44fe57c9902e6ee9bad4b
Installed quickdoc
$ clj -Tquickdoc quickdoc '{:github/repo "https://github.com/borkdude/quickdoc"}'
Syntax error compiling at (quickdoc/api.cljc:70:18).
Unable to resolve symbol: update-vals in this context

Full report at:
/tmp/clojure-15335704363100524426.edn
{:clojure.main/message
 "Syntax error compiling at (quickdoc/api.cljc:70:18).\nUnable to resolve symbol: update-vals in this context\n",
 :clojure.main/triage
 {:clojure.error/phase :compile-syntax-check,
  :clojure.error/line 70,
  :clojure.error/column 18,
  :clojure.error/source "api.cljc",
  :clojure.error/path "quickdoc/api.cljc",
  :clojure.error/class java.lang.RuntimeException,
  :clojure.error/cause
  "Unable to resolve symbol: update-vals in this context"},
 :clojure.main/trace
 {:via
  [{:type clojure.lang.Compiler$CompilerException,
    :message "Syntax error compiling at (quickdoc/api.cljc:70:18).",
    :data
    {:clojure.error/phase :compile-syntax-check,
     :clojure.error/line 70,
     :clojure.error/column 18,
     :clojure.error/source "quickdoc/api.cljc"},
    :at [clojure.lang.Compiler analyze "Compiler.java" 6812]}
   {:type java.lang.RuntimeException,
    :message "Unable to resolve symbol: update-vals in this context",
    :at [clojure.lang.Util runtimeException "Util.java" 221]}],
  :trace
  [[clojure.lang.Util runtimeException "Util.java" 221]
   [clojure.lang.Compiler resolveIn "Compiler.java" 7418]
   [clojure.lang.Compiler resolve "Compiler.java" 7362]
   [clojure.lang.Compiler analyzeSymbol "Compiler.java" 7323]
   [clojure.lang.Compiler analyze "Compiler.java" 6772]
   [clojure.lang.Compiler analyze "Compiler.java" 6749]
   [clojure.lang.Compiler$InvokeExpr parse "Compiler.java" 3824]
   [clojure.lang.Compiler analyzeSeq "Compiler.java" 7113]
   [clojure.lang.Compiler analyze "Compiler.java" 6793]
   [clojure.lang.Compiler access$300 "Compiler.java" 38]
   [clojure.lang.Compiler$LetExpr$Parser parse "Compiler.java" 6388]
   [clojure.lang.Compiler analyzeSeq "Compiler.java" 7111]
   [clojure.lang.Compiler analyze "Compiler.java" 6793]
   [clojure.lang.Compiler analyzeSeq "Compiler.java" 7099]
   [clojure.lang.Compiler analyze "Compiler.java" 6793]
   [clojure.lang.Compiler analyze "Compiler.java" 6749]
   [clojure.lang.Compiler$BodyExpr$Parser parse "Compiler.java" 6124]
   [clojure.lang.Compiler$FnMethod parse "Compiler.java" 5471]
   [clojure.lang.Compiler$FnExpr parse "Compiler.java" 4033]
   [clojure.lang.Compiler analyzeSeq "Compiler.java" 7109]
   [clojure.lang.Compiler analyze "Compiler.java" 6793]
   [clojure.lang.Compiler analyzeSeq "Compiler.java" 7099]
   [clojure.lang.Compiler analyze "Compiler.java" 6793]
   [clojure.lang.Compiler access$300 "Compiler.java" 38]
   [clojure.lang.Compiler$DefExpr$Parser parse "Compiler.java" 596]
   [clojure.lang.Compiler analyzeSeq "Compiler.java" 7111]
   [clojure.lang.Compiler analyze "Compiler.java" 6793]
   [clojure.lang.Compiler analyze "Compiler.java" 6749]
   [clojure.lang.Compiler eval "Compiler.java" 7185]
   [clojure.lang.Compiler load "Compiler.java" 7640]
   [clojure.lang.RT loadResourceScript "RT.java" 381]
   [clojure.lang.RT loadResourceScript "RT.java" 372]
   [clojure.lang.RT load "RT.java" 459]
   [clojure.lang.RT load "RT.java" 424]
   [clojure.core$load$fn__6856 invoke "core.clj" 6115]
   [clojure.core$load invokeStatic "core.clj" 6114]
   [clojure.core$load doInvoke "core.clj" 6098]
   [clojure.lang.RestFn invoke "RestFn.java" 408]
   [clojure.core$load_one invokeStatic "core.clj" 5897]
   [clojure.core$load_one invoke "core.clj" 5892]
   [clojure.core$load_lib$fn__6796 invoke "core.clj" 5937]
   [clojure.core$load_lib invokeStatic "core.clj" 5936]
   [clojure.core$load_lib doInvoke "core.clj" 5917]
   [clojure.lang.RestFn applyTo "RestFn.java" 142]
   [clojure.core$apply invokeStatic "core.clj" 669]
   [clojure.core$load_libs invokeStatic "core.clj" 5974]
   [clojure.core$load_libs doInvoke "core.clj" 5958]
   [clojure.lang.RestFn applyTo "RestFn.java" 137]
   [clojure.core$apply invokeStatic "core.clj" 669]
   [clojure.core$require invokeStatic "core.clj" 5996]
   [clojure.core$require doInvoke "core.clj" 5996]
   [clojure.lang.RestFn invoke "RestFn.java" 408]
   [clojure.run.exec$requiring_resolve_SINGLEQUOTE_
    invokeStatic
    "exec.clj"
    36]
   [clojure.run.exec$requiring_resolve_SINGLEQUOTE_
    invoke
    "exec.clj"
    29]
   [clojure.run.exec$exec invokeStatic "exec.clj" 43]
   [clojure.run.exec$exec doInvoke "exec.clj" 39]
   [clojure.lang.RestFn invoke "RestFn.java" 423]
   [clojure.run.exec$_main$fn__203 invoke "exec.clj" 177]
   [clojure.run.exec$_main invokeStatic "exec.clj" 173]
   [clojure.run.exec$_main doInvoke "exec.clj" 138]
   [clojure.lang.RestFn applyTo "RestFn.java" 137]
   [clojure.lang.Var applyTo "Var.java" 705]
   [clojure.core$apply invokeStatic "core.clj" 667]
   [clojure.main$main_opt invokeStatic "main.clj" 514]
   [clojure.main$main_opt invoke "main.clj" 510]
   [clojure.main$main invokeStatic "main.clj" 664]
   [clojure.main$main doInvoke "main.clj" 616]
   [clojure.lang.RestFn applyTo "RestFn.java" 137]
   [clojure.lang.Var applyTo "Var.java" 705]
   [clojure.main main "main.java" 40]],
  :cause "Unable to resolve symbol: update-vals in this context",
  :phase :compile-syntax-check}}

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.