Coder Social home page Coder Social logo

markdown-doclet's People

Contributors

abnaxos avatar frantam avatar fwbrasil avatar jenslohmann avatar loddar avatar slovdahl avatar turbo87 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

markdown-doclet's Issues

Change rendering of Wiki-style links

Wiki-style links should be rendered as link tags. I.e., ˋ[[Foo#bar() foobar]]ˋ should become ˋ{@link Foo#bar() foobar}ˋ.

The current way Wiki-style links are rendered doesn't make much sense, this is how Wiki-style links should work. Event though most people probably won't use them anyway and stick to ˋ{@link Foo#bar() foobar}ˋ, because IDEs will recognise these links. But still, that way, such links would actually make sense, at least for vi users. ;)

Note: This change breaks compatibility with older versions.

1.2 does not work

I am new to this doclet. I followed the documentation and put just this in my Gradle build file:

buildscript {
    repositories {
        mavenCentral() 
        jcenter()
    }
    dependencies {
        classpath "ch.raffael.pegdown-doclet:pegdown-doclet:${pegdown_doclet_version}"
    }
}
apply plugin: 'ch.raffael.pegdown-doclet'

... and the generated javadocs show that it is not kicking in.
I see other people do configurations and additional settings. Is this really necessary?

Unexpected spacing in code block when using {@literal @}

When I use {@literal @} to including @ symbols in code blocks then the line starts with one space to much.

Sample snippet in package-info.java:

/**
 * ```java
 * {@literal @}RunWith(AndroidJUnit4.class)
 * public class MyTest {
 *
 *   {@literal @}Rule
 *   public IntentsTestRule<MyActivity> activityTestRule = new IntentsTestRule<>(MyActivity.class);
 *
 * }
 * ```
 */

Expected result:

@RunWith(AndroidJUnit4.class)
public class MyTest {

  @Rule
  public IntentsTestRule<MyActivity> activityTestRule = new IntentsTestRule<>(MyActivity.class);

}

But result has one space to much at each @ symbol.

 @RunWith(AndroidJUnit4.class)
public class MyTest {

   @Rule
  public IntentsTestRule<MyActivity> activityTestRule = new IntentsTestRule<>(MyActivity.class);

}

For @Rule I can remove one space and then it looks correct but at @RunWith this workaround does not work.

Check for compatibility with JavaDoc 1.8

Check if there are any issues when using the doclet with JavaDoc 1.8 and fix them if needed. Also check whether there are any new features that need special support.

Ensure that the doclet remains compatible with JavaDoc 1.7.

Add support for inline tags

Inline tags are currently just left alone, as they don't interfere with Markdown syntax, usually. There is, however, an exception to this: If the extension SMARTS is enabled, it will break some links, e.g. in {@link String#format(String, Object...)} the three dots for varargs will be translated into a Unicode ELLIPSIS ('\u2026'), which is just plain wrong.

To work around this, we need to introduce a way to remove inline tags for rendering and re-insert them afterwards. While we're at it, adding tag renderers to inline tags may also enable some neat features. E.g., we could add an option to automatically add shortened labels to links, i.e. translate {@link String#format(String, Object...)} into {@link String#format(String, Object...) String.format()}.

A possibility to do this is to use Doc.inlineTags() replacing any non-text tags with an escape sequence ("\027<index>;"), process the markup and re-insert the tags at the escape sequences after optionally rendering them using a TagRenderer.

Enhance `-extensions` option

Enhance the -extensions to selectively disable some extensions. Right now, the list specified with -extensions replaces the default one. However, it would be nice to be able to only disable or enable single extensions:

  • -extensions -smartypants: Just disable Extensions.SMARTYPANTS
  • -extensions +fenced-code-blocks: Just enableExtensions.FENCED_CODE_BLOCKS`

Overview Page Not Included When Generating For Single Package

When JavaDoc is generated using the Pegdown Doclet and the only classes being included are from the single package, any included overview page is excluded.

Usage

Maven Plugin

Test Cases

  • All classes are in the same single package.
  • Classes are in various packages with all but one package in the excludePackageNames property.

Standard JavaDoc Behaviour

When using the standard JavaDoc Maven plugin, the above test cases still include the provided overview page.

Not working in methods in Android Studio 1.5.1

Strange thing, Pegdown works perfectly for classes and fields docs, but not for methods. No exceptions seems to be thrown. Demonstration:

byzanz-record

If it looks related to Android Studio to you, I'll file a new issue here.

Gist inline taglet {@gist <gist-id>}

It would be nice to include a gist inline tag in (javadoc).

Instead of including

/**
 *  Usage:
 *  <script src="https://gist.github.com/loddar/4ae8e534d7647d765b96.js"></script>
 */

(This is working with your doclet, but you need access to Github)

It would be nicer to have something like this which will be loaded from Github and included in generated javadoc.

/**
 *  Usage:
 *  {@gist 4ae8e534d7647d765b96} 
 */

While applying javadoc your doclet should read the Gist from this URI: https://api.github.com/gists/4ae8e534d7647d765b96 :

The result of this REST call will something like this:

{
  // omitted for brevity
   "files": {
    "MyAjUnit0Test.java": {
      "filename": "MyAjUnit0Test.java",
      "type": "text/plain",
      "language": "Java",
      "raw_url": "https://gist.githubusercontent.com/loddar/4ae8e534d7647d765b96/raw/912f0f845e215e1fd3d4ed16ae9aef39b3ce21ad/MyAjUnit0Test.java",
      "size": 390,
      "truncated": false,
      "content": "package com.company.project.aspects;\n\nimport org.failearly.ajunit.AjUnit4Test;\n\n/**\n * ajUnit - Initial Step 0 (create an ajUnit test).\n *\n * Create an JUnit4 Test by creating a test class extending AjUnit4Test.\n *\n * First error message:\n *\n *      ajUnit - Setup Error: Missing setup.\n *      - Please override setup(AjUnitSetup).\n *\n */\npublic class MyAjUnit0Test extends AjUnit4Test {\n}"
    }
  },

// ... rest omitted 

For each file (in this example: MyAjUnit0Test.java) there will be

  • a property: language
  • and a property: content.

The result of this inline tag should be:

Usage:
package com.company.project.aspects;

import org.failearly.ajunit.AjUnit4Test;

/**
 * ajUnit - Initial Step 0 (create an ajUnit test).
 *
 * Create an JUnit4 Test by creating a test class extending AjUnit4Test.
 *
 * First error message:
 *
 *      ajUnit - Setup Error: Missing setup.
 *      - Please override setup(AjUnitSetup).
 *
 */
public class MyAjUnit0Test extends AjUnit4Test {
}

May be you can use this: JavaDocSourceEmbed

It's nice but first it removes /** */ comments, and second it needs a preprocessing step, which IMHO is not necessary.

By the way, this should also solve your issue with java annotations.

background.gif and other resources missing when running with Java 8

When running using the Java 8 version of javadoc, the resources/*.gif files are not included. This is presumably because those files are not used by the new Java 8 default stylesheet.

I've worked around this by having a little script in my pom file download the resource files from the Java 7 API website during the build process, but this isn't really ideal.

Integrate highlight.js

Integrate highlight.js for syntax highlighting code blocks:

```java
public class FooBar {
}
```

If no language is specified, the code should not be hightlighted (don't try to guess the language).

Markdown not being processed in package-info.java files

I have a Gradle project:

group 'us.juggl.twentyfifteen'
version '1.0-SNAPSHOT'

apply plugin: 'java'
apply plugin: 'application'

sourceCompatibility = 1.8

mainClassName = 'us.juggl.twentyfifteen.november.annotations.Main'

repositories {
    mavenCentral()
}

configurations {
    markdownDoclet
}

javadoc.options {
    docletpath = configurations.markdownDoclet.files.asType(List) // gradle should relly make this simpler
    doclet = "ch.raffael.doclets.pegdown.PegdownDoclet"
    addStringOption("parse-timeout", "10")
}

dependencies {
    compile group: 'org.projectlombok', name: 'lombok', version: '1.16.6'
    compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.12'
    testCompile group: 'junit', name: 'junit', version: '4.11'
    runtime group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: '2.4.1'
    runtime group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.4.1'
    markdownDoclet group: 'ch.raffael.pegdown-doclet', name: 'pegdown-doclet', version: '1.1.1'
}

And inside of src/main/java/us/juggl/twentyfifteen/november/annotations/ I have a package-info.java file for the package level JavaDocs. Pegdown is not processing the markdown in that file, I just see raw text in the generated JavaDocs.

Javadocs task fails when building project

I cloned the project locally and ran the "clean build" command. I didn't modify any sources.

gradle clean build

:clean UP-TO-DATE
:integrations:clean UP-TO-DATE
:integrations:gradle-plugin:clean UP-TO-DATE
:integrations:idea-plugin:clean UP-TO-DATE
:compileJava
:compileGroovy UP-TO-DATE
:processResources
:classes
:jar
:allJar
:javadoc
javadoc: error - Illegal package name: "<a"
javadoc: error - Illegal package name: "href="
javadoc: error - Illegal package name: "https://github.com/Abnaxos/pegdown-doclet/"
javadoc: error - Illegal package name: "target="
javadoc: error - Illegal package name: ">"
javadoc: error - Illegal package name: "<img"
javadoc: error - Illegal package name: "style="
javadoc: error - Illegal package name: "position: absolute; top: 0; right: 0; border: 0;"
javadoc: error - Illegal package name: "src="
javadoc: error - Illegal package name: "https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png"
javadoc: error - Illegal package name: "alt="
javadoc: error - Illegal package name: "Fork me on GitHub"
javadoc: error - Illegal package name: ">"
javadoc: error - Illegal package name: ""
javadoc: error - Illegal package name: ""
javadoc: warning - No source files for package _top
15 errors
1 warning
:javadoc FAILED

FAILURE: Build failed with an exception.

  • What went wrong:
    Execution failed for task ':javadoc'.

    Javadoc generation failed.

  • Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 18.459 secs

I also see errors like this:

15:25:12.848 [DEBUG] [org.gradle.api.internal.artifacts.ivyservice.ivyresolve.RepositoryChainDependencyResolver] Using module 'org.parboiled:parboiled-core:1.1.5' from repository 'BintrayJCenter'
15:25:12.864 [DEBUG] [org.gradle.api.internal.artifacts.ivyservice.ivyresolve.RepositoryChainDependencyResolver] Discarding resolve failure.
java.lang.NullPointerException
at org.gradle.api.internal.artifacts.repositories.resolver.MavenLocalResolver.isOrphanedPom(MavenLocalResolver.java:49)
at org.gradle.api.internal.artifacts.repositories.resolver.MavenLocalResolver.findMetaDataArtifact(MavenLocalResolver.java:42)

15:25:12.474 [DEBUG] [org.gradle.api.internal.artifacts.ivyservice.ivyresolve.RepositoryChainDependencyResolver] Using module 'com.google.guava:guava:18.0' from repository 'BintrayJCenter'
15:25:12.474 [DEBUG] [org.gradle.api.internal.artifacts.ivyservice.ivyresolve.RepositoryChainDependencyResolver] Discarding resolve failure.
java.lang.NullPointerException
at org.gradle.api.internal.artifacts.repositories.resolver.MavenLocalResolver.isOrphanedPom(MavenLocalResolver.java:49)
at org.gradle.api.internal.artifacts.repositories.resolver.MavenLocalResolver.findMetaDataArtifact(MavenLocalResolver.java:42)

[gradle support] gradle plugin not found at jcenter

I'm trying to follow the process in README.md of the gradle-plugin. gradlew tasks gives me following output in my project:

> Could not resolve all dependencies for configuration ':classpath'.
   > Could not find ch.raffael.pegdown-doclet:gradle-plugin:1.0.
     Searched in the following locations:
         https://jcenter.bintray.com/ch/raffael/pegdown-doclet/gradle-plugin/1.0/gradle-plugin-1.0.pom
         https://jcenter.bintray.com/ch/raffael/pegdown-doclet/gradle-plugin/1.0/gradle-plugin-1.0.jar
         https://plugins.gradle.org/m2/ch/raffael/pegdown-doclet/gradle-plugin/1.0/gradle-plugin-1.0.pom
         https://plugins.gradle.org/m2/ch/raffael/pegdown-doclet/gradle-plugin/1.0/gradle-plugin-1.0.jar

When browsing https://jcenter.bintray.com/ch/raffael/pegdown-doclet/, only pegdown-doclet/ appears.

Warning - Multiple sources of package comments found

JavaDoc complains about multiple sources for package comments. setRawCommentText() checks that it's been called only once -- if both package.html and package-info.java exists, this method would be called twice, therefore JavaDoc issues a warning on the second call.

In this case, however, the second call originates in the docs being converted from HTML to Markdown.

Find a workaround.

Would you consider changing the license?

First of all, thanks a lot for this very useful tool; I very much like documenting my code with a modern documentation syntax.

I would like to use the tool but the project I am working on doesn't allow GPL3. I am wondering whether you would be willing to change the license to something else, possibly the Apache license?

From the Github history I see that GPL3 is needed because of PlantUML. I quickly checked their website and see that they allow the Apache License, see here.

In case you could imagine making such a change, I'd be happy to come up with a PR, of course.

Links (@link) not resolving in IDEA.

Using the IDEA plugin, the links are detected but they are displayed in red in the help tooltip (the one you get by pressing Ctrl + Q) and clicking on them makes an error pop-up.

Here's the red link (the docstring was simply {@link #main}):

The error message says "Windows cannot find PATH Make sure you typed the name correctly, and then try again.", where PATH is the following:

A list isn't created unless there's an empty line preceding it

This is the output produced by the code below the picture (using version 1.1.1 of pegdown-doclet):

Javadoc output

public class TestJavadoc {

    /**
     * Testing
     * - this is a list
     * - even more listing
     */
    public void test() {}

    /**
     * Testing
     *
     * - this is a list
     * - even more listing
     */
    public void test2() {}
}

Why is a line break needed before the list? It works fine without a line break on eg. github.

Testing
- this is a list
- even more listing

results in:

Testing

  • this is a list
  • even more listing

Assertion failed at PsiParameterListImpl.getParameterIndex at PegdownDocumentationProvider.generateDoc

Assertion failed
java.lang.Throwable
    at com.intellij.openapi.diagnostic.Logger.assertTrue(Logger.java:156)
    at com.intellij.openapi.diagnostic.Logger.assertTrue(Logger.java:165)
    at com.intellij.psi.impl.source.PsiParameterListImpl.getParameterIndex(PsiParameterListImpl.java:50)
    at com.intellij.psi.util.PsiFormatUtil.getExternalName(PsiFormatUtil.java:446)
    at com.intellij.codeInsight.BaseExternalAnnotationsManager.getExternalName(BaseExternalAnnotationsManager.java:80)
    at com.intellij.codeInsight.BaseExternalAnnotationsManager.doCollect(BaseExternalAnnotationsManager.java:208)
    at com.intellij.codeInsight.BaseExternalAnnotationsManager.collectExternalAnnotations(BaseExternalAnnotationsManager.java:146)
    at com.intellij.codeInsight.BaseExternalAnnotationsManager.findExternalAnnotations(BaseExternalAnnotationsManager.java:123)
    at com.intellij.codeInsight.javadoc.JavaDocInfoGenerator.generateAnnotations(JavaDocInfoGenerator.java:918)
    at com.intellij.codeInsight.javadoc.JavaDocInfoGenerator.generateMethodParameterJavaDoc(JavaDocInfoGenerator.java:1058)
    at com.intellij.codeInsight.javadoc.JavaDocInfoGenerator.generateDocInfoCore(JavaDocInfoGenerator.java:396)
    at com.intellij.codeInsight.javadoc.JavaDocInfoGenerator.generateDocInfo(JavaDocInfoGenerator.java:437)
    at com.intellij.lang.java.JavaDocumentationProvider.generateExternalJavadoc(JavaDocumentationProvider.java:554)
    at com.intellij.lang.java.JavaDocumentationProvider.generateDoc(JavaDocumentationProvider.java:542)
    at ch.raffael.doclets.pegdown.integrations.idea.PegdownDocumentationProvider.generateDoc(PegdownDocumentationProvider.java:135)
    at com.intellij.lang.documentation.CompositeDocumentationProvider.generateDoc(CompositeDocumentationProvider.java:144)
    at com.intellij.codeInsight.navigation.CtrlMouseHandler$9$1.run(CtrlMouseHandler.java:666)
    at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:950)
    at com.intellij.codeInsight.navigation.CtrlMouseHandler$9.run(CtrlMouseHandler.java:661)
    at com.intellij.util.concurrency.QueueProcessor.runSafely(QueueProcessor.java:238)
    at com.intellij.util.Alarm$Request$1.run(Alarm.java:378)
    at com.intellij.util.Alarm$Request.run(Alarm.java:389)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at com.intellij.util.concurrency.SchedulingWrapper$MyScheduledFutureTask.run(SchedulingWrapper.java:227)
    at com.intellij.util.concurrency.BoundedTaskExecutor$2.run(BoundedTaskExecutor.java:187)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

running IntelliJ Idea 2016.1 RC1

Example text that which hangs

This is an extreme case, so closing this without further investigation is totally valid :)

The following text [A], when placed in a package-info.java file, will cause pegdown doclet to fail with:

package-info.java:151: error - Error while parsing action 'Root/Sequence/ZeroOrMore/Sequence/Block/FirstOf/Table/Sequence/Optional/Sequence/NodeSequence/Sequence/TableRow/Sequence/OneOrMore/Sequence/TableCell/NodeSequence/Sequence/OneOrMore/Sequence/Inline/Inline_Action1' at input position (line 27, pos 1):
<p>To register your listener methods with the event producers...

But the twice as large text [B] (which has the same beginning, but is a little longer) will cause the pegdown doclet to hang forever (or at least 10 minutes).

I was able to get it to pass by converting to [C]. All of this is with 1.3.0.

[A]

/**
 * The EventBus allows publish-subscribe-style communication between components
 * without requiring the components to explicitly register with one another
 * (and thus be aware of each other).  It is designed exclusively to replace
 * traditional Java in-process event distribution using explicit registration.
 * It is <em>not</em> a general-purpose publish-subscribe system, nor is it
 * intended for interprocess communication.
 * 
 * <p>See the Guava User Guide article on <a href=
 * "https://github.com/google/guava/wiki/EventBusExplained">
 * {@code EventBus}</a>.
 *
 * <h2>One-Minute Guide</h2>
 *
 * <p>Converting an existing EventListener-based system to use the EventBus is
 * easy.
 *
 * <h3>For Listeners</h3>
 * <p>To listen for a specific flavor of event (say, a CustomerChangeEvent)...
 * <ul>
 * <li><strong>...in traditional Java events:</strong> implement an interface
 *     defined with the event &mdash; such as CustomerChangeEventListener.</li>
 * <li><strong>...with EventBus:</strong> create a method that accepts
 *     CustomerChangeEvent as its sole argument, and mark it with the
 *     {@link com.diffplug.common.eventbus.Subscribe} annotation.</li>
 * </ul>
 *
 * <p>To register your listener methods with the event producers...
 * <ul>
 * <li><strong>...in traditional Java events:</strong> pass your object to each
 *     producer's {@code registerCustomerChangeEventListener} method.  These
 *     methods are rarely defined in common interfaces, so in addition to
 *     knowing every possible producer, you must also know its type.</li>
 * <li><strong>...with EventBus:</strong> pass your object to the
 *     {@link com.diffplug.common.eventbus.EventBus#register(Object)} method on an
 *     EventBus.  You'll need to
 *     make sure that your object shares an EventBus instance with the event
 *     producers.</li>
 * </ul>
 *
 * <p>To listen for a common event supertype (such as EventObject or Object)...
 * <ul>
 * <li><strong>...in traditional Java events:</strong> not easy.</li>
 * <li><strong>...with EventBus:</strong> events are automatically dispatched to
 *     listeners of any supertype, allowing listeners for interface types
 *     or "wildcard listeners" for Object.</li>
 * </ul>
 *
 * <p>To listen for and detect events that were dispatched without listeners...
 * <ul>
 * <li><strong>...in traditional Java events:</strong> add code to each
 *     event-dispatching method (perhaps using AOP).</li>
 * <li><strong>...with EventBus:</strong> subscribe to {@link
 *     com.diffplug.common.eventbus.DeadEvent}.  The
 *     EventBus will notify you of any events that were posted but not
 *     delivered.  (Handy for debugging.)</li>
 * </ul>
 *
 * <h3>For Producers</h3>
 * <p>To keep track of listeners to your events...
 * <ul>
 * <li><strong>...in traditional Java events:</strong> write code to manage
 *     a list of listeners to your object, including synchronization, or use a
 *     utility class like EventListenerList.</li>
 * <li><strong>...with EventBus:</strong> EventBus does this for you.</li>
 * </ul>
 *
 * <p>To dispatch an event to listeners...
 * <ul>
 * <li><strong>...in traditional Java events:</strong> write a method to
 *     dispatch events to each event listener, including error isolation and
 *     (if desired) asynchronicity.</li>
 * <li><strong>...with EventBus:</strong> pass the event object to an EventBus's
 *     {@link com.diffplug.common.eventbus.EventBus#post(Object)} method.</li>
 * </ul>
 *
 * <h2>Glossary</h2>
 *
 * <p>The EventBus system and code use the following terms to discuss event
 * distribution:
 * <dl>
 * <dt>Event</dt><dd>Any object that may be <em>posted</em> to a bus.</dd>
 * <dt>Subscribing</dt><dd>The act of registering a <em>listener</em> with an
 *     EventBus, so that its <em>subscriber methods</em> will receive events.</dd>
 * <dt>Listener</dt><dd>An object that wishes to receive events, by exposing
 *     <em>subscriber methods</em>.</dt>
 * <dt>Subscriber method</dt><dd>A public method that the EventBus should use to
 *     deliver <em>posted</em> events.  Subscriber methods are marked by the
 *     {@link com.diffplug.common.eventbus.Subscribe} annotation.</dd>
 * <dt>Posting an event</dt><dd>Making the event available to any
 *     <em>listeners</em> through the EventBus.</dt>
 * </dl>
 *
 * <h2>FAQ</h2>
 * <h3>Why must I create my own Event Bus, rather than using a singleton?</h3>
 *
 * <p>The Event Bus doesn't specify how you use it; there's nothing stopping your
 * application from having separate EventBus instances for each component, or
 * using separate instances to separate events by context or topic.  This also
 * makes it trivial to set up and tear down EventBus objects in your tests.
 *
 * <p>Of course, if you'd like to have a process-wide EventBus singleton,
 * there's nothing stopping you from doing it that way.  Simply have your
 * container (such as Guice) create the EventBus as a singleton at global scope
 * (or stash it in a static field, if you're into that sort of thing).
 *
 * <p>In short, the EventBus is not a singleton because we'd rather not make
 * that decision for you.  Use it how you like.
 *
 * <h3>Why use an annotation to mark subscriber methods, rather than requiring the
 * listener to implement an interface?</h3>
 * <p>We feel that the Event Bus's {@code @Subscribe} annotation conveys your
 * intentions just as explicitly as implementing an interface (or perhaps more
 * so), while leaving you free to place event subscriber methods wherever you wish
 * and give them intention-revealing names.
 *
 * <p>Traditional Java Events use a listener interface which typically sports
 * only a handful of methods -- typically one.  This has a number of
 * disadvantages:
 * <ul>
 *   <li>Any one class can only implement a single response to a given event.
 *   <li>Listener interface methods may conflict.
 *   <li>The method must be named after the event (e.g. {@code
 *       handleChangeEvent}), rather than its purpose (e.g. {@code
 *       recordChangeInJournal}).
 *   <li>Each event usually has its own interface, without a common parent
 *       interface for a family of events (e.g. all UI events).
 * </ul>
 *
 * <p>The difficulties in implementing this cleanly has given rise to a pattern,
 * particularly common in Swing apps, of using tiny anonymous classes to
 * implement event listener interfaces.
 * 
 */

[B]

/**
 * The EventBus allows publish-subscribe-style communication between components
 * without requiring the components to explicitly register with one another
 * (and thus be aware of each other).  It is designed exclusively to replace
 * traditional Java in-process event distribution using explicit registration.
 * It is <em>not</em> a general-purpose publish-subscribe system, nor is it
 * intended for interprocess communication.
 * 
 * <p>See the Guava User Guide article on <a href=
 * "https://github.com/google/guava/wiki/EventBusExplained">
 * {@code EventBus}</a>.
 *
 * <h2>One-Minute Guide</h2>
 *
 * <p>Converting an existing EventListener-based system to use the EventBus is
 * easy.
 *
 * <h3>For Listeners</h3>
 * <p>To listen for a specific flavor of event (say, a CustomerChangeEvent)...
 * <ul>
 * <li><strong>...in traditional Java events:</strong> implement an interface
 *     defined with the event &mdash; such as CustomerChangeEventListener.</li>
 * <li><strong>...with EventBus:</strong> create a method that accepts
 *     CustomerChangeEvent as its sole argument, and mark it with the
 *     {@link com.diffplug.common.eventbus.Subscribe} annotation.</li>
 * </ul>
 *
 * <p>To register your listener methods with the event producers...
 * <ul>
 * <li><strong>...in traditional Java events:</strong> pass your object to each
 *     producer's {@code registerCustomerChangeEventListener} method.  These
 *     methods are rarely defined in common interfaces, so in addition to
 *     knowing every possible producer, you must also know its type.</li>
 * <li><strong>...with EventBus:</strong> pass your object to the
 *     {@link com.diffplug.common.eventbus.EventBus#register(Object)} method on an
 *     EventBus.  You'll need to
 *     make sure that your object shares an EventBus instance with the event
 *     producers.</li>
 * </ul>
 *
 * <p>To listen for a common event supertype (such as EventObject or Object)...
 * <ul>
 * <li><strong>...in traditional Java events:</strong> not easy.</li>
 * <li><strong>...with EventBus:</strong> events are automatically dispatched to
 *     listeners of any supertype, allowing listeners for interface types
 *     or "wildcard listeners" for Object.</li>
 * </ul>
 *
 * <p>To listen for and detect events that were dispatched without listeners...
 * <ul>
 * <li><strong>...in traditional Java events:</strong> add code to each
 *     event-dispatching method (perhaps using AOP).</li>
 * <li><strong>...with EventBus:</strong> subscribe to {@link
 *     com.diffplug.common.eventbus.DeadEvent}.  The
 *     EventBus will notify you of any events that were posted but not
 *     delivered.  (Handy for debugging.)</li>
 * </ul>
 *
 * <h3>For Producers</h3>
 * <p>To keep track of listeners to your events...
 * <ul>
 * <li><strong>...in traditional Java events:</strong> write code to manage
 *     a list of listeners to your object, including synchronization, or use a
 *     utility class like EventListenerList.</li>
 * <li><strong>...with EventBus:</strong> EventBus does this for you.</li>
 * </ul>
 *
 * <p>To dispatch an event to listeners...
 * <ul>
 * <li><strong>...in traditional Java events:</strong> write a method to
 *     dispatch events to each event listener, including error isolation and
 *     (if desired) asynchronicity.</li>
 * <li><strong>...with EventBus:</strong> pass the event object to an EventBus's
 *     {@link com.diffplug.common.eventbus.EventBus#post(Object)} method.</li>
 * </ul>
 *
 * <h2>Glossary</h2>
 *
 * <p>The EventBus system and code use the following terms to discuss event
 * distribution:
 * <dl>
 * <dt>Event</dt><dd>Any object that may be <em>posted</em> to a bus.</dd>
 * <dt>Subscribing</dt><dd>The act of registering a <em>listener</em> with an
 *     EventBus, so that its <em>subscriber methods</em> will receive events.</dd>
 * <dt>Listener</dt><dd>An object that wishes to receive events, by exposing
 *     <em>subscriber methods</em>.</dt>
 * <dt>Subscriber method</dt><dd>A public method that the EventBus should use to
 *     deliver <em>posted</em> events.  Subscriber methods are marked by the
 *     {@link com.diffplug.common.eventbus.Subscribe} annotation.</dd>
 * <dt>Posting an event</dt><dd>Making the event available to any
 *     <em>listeners</em> through the EventBus.</dt>
 * </dl>
 *
 * <h2>FAQ</h2>
 * <h3>Why must I create my own Event Bus, rather than using a singleton?</h3>
 *
 * <p>The Event Bus doesn't specify how you use it; there's nothing stopping your
 * application from having separate EventBus instances for each component, or
 * using separate instances to separate events by context or topic.  This also
 * makes it trivial to set up and tear down EventBus objects in your tests.
 *
 * <p>Of course, if you'd like to have a process-wide EventBus singleton,
 * there's nothing stopping you from doing it that way.  Simply have your
 * container (such as Guice) create the EventBus as a singleton at global scope
 * (or stash it in a static field, if you're into that sort of thing).
 *
 * <p>In short, the EventBus is not a singleton because we'd rather not make
 * that decision for you.  Use it how you like.
 *
 * <h3>Why use an annotation to mark subscriber methods, rather than requiring the
 * listener to implement an interface?</h3>
 * <p>We feel that the Event Bus's {@code @Subscribe} annotation conveys your
 * intentions just as explicitly as implementing an interface (or perhaps more
 * so), while leaving you free to place event subscriber methods wherever you wish
 * and give them intention-revealing names.
 *
 * <p>Traditional Java Events use a listener interface which typically sports
 * only a handful of methods -- typically one.  This has a number of
 * disadvantages:
 * <ul>
 *   <li>Any one class can only implement a single response to a given event.
 *   <li>Listener interface methods may conflict.
 *   <li>The method must be named after the event (e.g. {@code
 *       handleChangeEvent}), rather than its purpose (e.g. {@code
 *       recordChangeInJournal}).
 *   <li>Each event usually has its own interface, without a common parent
 *       interface for a family of events (e.g. all UI events).
 * </ul>
 *
 * <p>The difficulties in implementing this cleanly has given rise to a pattern,
 * particularly common in Swing apps, of using tiny anonymous classes to
 * implement event listener interfaces.
 *
 * <p>Compare these two cases: <pre>
 *   class ChangeRecorder {
 *     void setCustomer(Customer cust) {
 *       cust.addChangeListener(new ChangeListener() {
 *         void customerChanged(ChangeEvent e) {
 *           recordChange(e.getChange());
 *         }
 *       };
 *     }
 *   }
 *
 *   // Class is typically registered by the container.
 *   class EventBusChangeRecorder {
 *     &#064;Subscribe void recordCustomerChange(ChangeEvent e) {
 *       recordChange(e.getChange());
 *     }
 *   }</pre>
 *
 * <p>The intent is actually clearer in the second case: there's less noise code,
 * and the event subscriber has a clear and meaningful name.
 *
 * <h3>What about a generic {@code Subscriber<T>} interface?</h3>
 * <p>Some have proposed a generic {@code Subscriber<T>} interface for EventBus
 * listeners.  This runs into issues with Java's use of type erasure, not to
 * mention problems in usability.
 *
 * <p>Let's say the interface looked something like the following: <pre>   {@code
 *   interface Subscriber<T> {
 *     void handleEvent(T event);
 *   }}</pre>
 *
 * <p>Due to erasure, no single class can implement a generic interface more than
 * once with different type parameters.  This is a giant step backwards from
 * traditional Java Events, where even if {@code actionPerformed} and {@code
 * keyPressed} aren't very meaningful names, at least you can implement both
 * methods!
 *
 * <h3>Doesn't EventBus destroy static typing and eliminate automated
 * refactoring support?</h3>
 * <p>Some have freaked out about EventBus's {@code register(Object)} and {@code
 * post(Object)} methods' use of the {@code Object} type.
 *
 * <p>{@code Object} is used here for a good reason: the Event Bus library
 * places no restrictions on the types of either your event listeners (as in
 * {@code register(Object)}) or the events themselves (in {@code post(Object)}).
 *
 * <p>Event subscriber methods, on the other hand, must explicitly declare their
 * argument type -- the type of event desired (or one of its supertypes).  Thus,
 * searching for references to an event class will instantly find all subscriber
 * methods for that event, and renaming the type will affect all subscriber methods
 * within view of your IDE (and any code that creates the event).
 *
 * <p>It's true that you can rename your {@code @Subscribed} event subscriber
 * methods at will; Event Bus will not stop this or do anything to propagate the
 * rename because, to Event Bus, the names of your subscriber methods are
 * irrelevant.  Test code that calls the methods directly, of course, will be
 * affected by your renaming -- but that's what your refactoring tools are for.
 *
 * <h3>What happens if I {@code register} a listener without any subscriber
 * methods?</h3>
 * <p>Nothing at all.
 *
 * <p>The Event Bus was designed to integrate with containers and module
 * systems, with Guice as the prototypical example.  In these cases, it's
 * convenient to have the container/factory/environment pass <i>every</i>
 * created object to an EventBus's {@code register(Object)} method.
 *
 * <p>This way, any object created by the container/factory/environment can
 * hook into the system's event model simply by exposing subscriber methods.
 *
 * <h3>What Event Bus problems can be detected at compile time?</h3>
 * <p>Any problem that can be unambiguously detected by Java's type system.  For
 * example, defining a subscriber method for a nonexistent event type.
 *
 * <h3>What Event Bus problems can be detected immediately at registration?</h3>
 * <p>Immediately upon invoking {@code register(Object)}, the listener being
 * registered is checked for the <i>well-formedness</i> of its subscriber methods.
 * Specifically, any methods marked with {@code @Subscribe} must take only a
 * single argument.
 *
 * <p>Any violations of this rule will cause an {@code IllegalArgumentException}
 * to be thrown.
 *
 * <p>(This check could be moved to compile-time using APT, a solution we're
 * researching.)
 *
 * <h3>What Event Bus problems may only be detected later, at runtime?</h3>
 * <p>If a component posts events with no registered listeners, it <i>may</i>
 * indicate an error (typically an indication that you missed a
 * {@code @Subscribe} annotation, or that the listening component is not loaded).
 *
 * <p>(Note that this is <i>not necessarily</i> indicative of a problem.  There
 * are many cases where an application will deliberately ignore a posted event,
 * particularly if the event is coming from code you don't control.)
 *
 * <p>To handle such events, register a subscriber method for the {@code DeadEvent}
 * class.  Whenever EventBus receives an event with no registered subscribers, it
 * will turn it into a {@code DeadEvent} and pass it your way -- allowing you to
 * log it or otherwise recover.
 *
 * <h3>How do I test event listeners and their subscriber methods?</h3>
 * <p>Because subscriber methods on your listener classes are normal methods, you can
 * simply call them from your test code to simulate the EventBus.
 */

[C]

/**
 * The EventBus allows publish-subscribe-style communication between components
 * without requiring the components to explicitly register with one another
 * (and thus be aware of each other).  It is designed exclusively to replace
 * traditional Java in-process event distribution using explicit registration.
 * It is <em>not</em> a general-purpose publish-subscribe system, nor is it
 * intended for interprocess communication.
 * 
 * See the Guava User Guide article on <a href=
 * "https://github.com/google/guava/wiki/EventBusExplained">
 * {@code EventBus}</a>.
 *
 * <h2>One-Minute Guide</h2>
 *
 * Converting an existing EventListener-based system to use the EventBus is
 * easy.
 *
 * <h3>For Listeners</h3>
 * To listen for a specific flavor of event (say, a CustomerChangeEvent)...
 * <ul>
 * <li><strong>...in traditional Java events:</strong> implement an interface
 *     defined with the event &mdash; such as CustomerChangeEventListener.</li>
 * <li><strong>...with EventBus:</strong> create a method that accepts
 *     CustomerChangeEvent as its sole argument, and mark it with the
 *     {@link com.diffplug.common.eventbus.Subscribe} annotation.</li>
 * </ul>
 *
 * To register your listener methods with the event producers...
 * <ul>
 * <li><strong>...in traditional Java events:</strong> pass your object to each
 *     producer's {@code registerCustomerChangeEventListener} method.  These
 *     methods are rarely defined in common interfaces, so in addition to
 *     knowing every possible producer, you must also know its type.</li>
 * <li><strong>...with EventBus:</strong> pass your object to the
 *     {@link com.diffplug.common.eventbus.EventBus#register(Object)} method on an
 *     EventBus.  You'll need to
 *     make sure that your object shares an EventBus instance with the event
 *     producers.</li>
 * </ul>
 *
 * To listen for a common event supertype (such as EventObject or Object)...
 * <ul>
 * <li><strong>...in traditional Java events:</strong> not easy.</li>
 * <li><strong>...with EventBus:</strong> events are automatically dispatched to
 *     listeners of any supertype, allowing listeners for interface types
 *     or "wildcard listeners" for Object.</li>
 * </ul>
 *
 * To listen for and detect events that were dispatched without listeners...
 * <ul>
 * <li><strong>...in traditional Java events:</strong> add code to each
 *     event-dispatching method (perhaps using AOP).</li>
 * <li><strong>...with EventBus:</strong> subscribe to {@link
 *     com.diffplug.common.eventbus.DeadEvent}.  The
 *     EventBus will notify you of any events that were posted but not
 *     delivered.  (Handy for debugging.)</li>
 * </ul>
 *
 * <h3>For Producers</h3>
 * To keep track of listeners to your events...
 * <ul>
 * <li><strong>...in traditional Java events:</strong> write code to manage
 *     a list of listeners to your object, including synchronization, or use a
 *     utility class like EventListenerList.</li>
 * <li><strong>...with EventBus:</strong> EventBus does this for you.</li>
 * </ul>
 *
 * To dispatch an event to listeners...
 * <ul>
 * <li><strong>...in traditional Java events:</strong> write a method to
 *     dispatch events to each event listener, including error isolation and
 *     (if desired) asynchronicity.</li>
 * <li><strong>...with EventBus:</strong> pass the event object to an EventBus's
 *     {@link com.diffplug.common.eventbus.EventBus#post(Object)} method.</li>
 * </ul>
 *
 * <h2>Glossary</h2>
 *
 * The EventBus system and code use the following terms to discuss event
 * distribution:
 *
 * - **Event**: Any object that may be <em>posted</em> to a bus.
 * - **Subscribing**: The act of registering a <em>listener</em> with an
 *     EventBus, so that its <em>subscriber methods</em> will receive events.
 * - **Listener**: An object that wishes to receive events, by exposing
 *     <em>subscriber methods</em>.
 * - **Subscriber method**: A public method that the EventBus should use to
 *     deliver <em>posted</em> events.  Subscriber methods are marked by the
 *     {@link com.diffplug.common.eventbus.Subscribe} annotation.
 * **Posting an event**: Making the event available to any
 *     <em>listeners</em> through the EventBus.
 *
 * <h2>FAQ</h2>
 * <h3>Why must I create my own Event Bus, rather than using a singleton?</h3>
 *
 * The Event Bus doesn't specify how you use it; there's nothing stopping your
 * application from having separate EventBus instances for each component, or
 * using separate instances to separate events by context or topic.  This also
 * makes it trivial to set up and tear down EventBus objects in your tests.
 *
 * Of course, if you'd like to have a process-wide EventBus singleton,
 * there's nothing stopping you from doing it that way.  Simply have your
 * container (such as Guice) create the EventBus as a singleton at global scope
 * (or stash it in a static field, if you're into that sort of thing).
 *
 * In short, the EventBus is not a singleton because we'd rather not make
 * that decision for you.  Use it how you like.
 *
 * <h3>Why use an annotation to mark subscriber methods, rather than requiring the
 * listener to implement an interface?</h3>
 * We feel that the Event Bus's {@code @Subscribe} annotation conveys your
 * intentions just as explicitly as implementing an interface (or perhaps more
 * so), while leaving you free to place event subscriber methods wherever you wish
 * and give them intention-revealing names.
 *
 * Traditional Java Events use a listener interface which typically sports
 * only a handful of methods -- typically one.  This has a number of
 * disadvantages:
 * <ul>
 *   <li>Any one class can only implement a single response to a given event.
 *   <li>Listener interface methods may conflict.
 *   <li>The method must be named after the event (e.g. {@code
 *       handleChangeEvent}), rather than its purpose (e.g. {@code
 *       recordChangeInJournal}).
 *   <li>Each event usually has its own interface, without a common parent
 *       interface for a family of events (e.g. all UI events).
 * </ul>
 *
 * The difficulties in implementing this cleanly has given rise to a pattern,
 * particularly common in Swing apps, of using tiny anonymous classes to
 * implement event listener interfaces.
 *
 * Compare these two cases:
 * <pre>{@code class ChangeRecorder {
 *   void setCustomer(Customer cust) {
 *     cust.addChangeListener(new ChangeListener() {
 *       void customerChanged(ChangeEvent e) {
 *         recordChange(e.getChange());
 *       }
 *     };
 *   }
 * }
 *
 * // Class is typically registered by the container.
 * class EventBusChangeRecorder {
 *   &#064;Subscribe void recordCustomerChange(ChangeEvent e) {
 *     recordChange(e.getChange());
 *   }
 * }
 * }</pre>
 *
 * The intent is actually clearer in the second case: there's less noise code,
 * and the event subscriber has a clear and meaningful name.
 *
 * <h3>What about a generic {@code Subscriber<T>} interface?</h3>
 * Some have proposed a generic {@code Subscriber<T>} interface for EventBus
 * listeners.  This runs into issues with Java's use of type erasure, not to
 * mention problems in usability.
 *
 * Let's say the interface looked something like the following:
 * <pre>{@code interface Subscriber<T> {
 *    void handleEvent(T event);
 *  }}</pre>
 *
 * Due to erasure, no single class can implement a generic interface more than
 * once with different type parameters.  This is a giant step backwards from
 * traditional Java Events, where even if {@code actionPerformed} and {@code
 * keyPressed} aren't very meaningful names, at least you can implement both
 * methods!
 *
 * <h3>Doesn't EventBus destroy static typing and eliminate automated
 * refactoring support?</h3>
 * Some have freaked out about EventBus's {@code register(Object)} and {@code
 * post(Object)} methods' use of the {@code Object} type.
 *
 * {@code Object} is used here for a good reason: the Event Bus library
 * places no restrictions on the types of either your event listeners (as in
 * {@code register(Object)}) or the events themselves (in {@code post(Object)}).
 *
 * Event subscriber methods, on the other hand, must explicitly declare their
 * argument type -- the type of event desired (or one of its supertypes).  Thus,
 * searching for references to an event class will instantly find all subscriber
 * methods for that event, and renaming the type will affect all subscriber methods
 * within view of your IDE (and any code that creates the event).
 *
 * It's true that you can rename your {@code @Subscribed} event subscriber
 * methods at will; Event Bus will not stop this or do anything to propagate the
 * rename because, to Event Bus, the names of your subscriber methods are
 * irrelevant.  Test code that calls the methods directly, of course, will be
 * affected by your renaming -- but that's what your refactoring tools are for.
 *
 * <h3>What happens if I {@code register} a listener without any subscriber
 * methods?</h3>
 * Nothing at all.
 *
 * The Event Bus was designed to integrate with containers and module
 * systems, with Guice as the prototypical example.  In these cases, it's
 * convenient to have the container/factory/environment pass <i>every</i>
 * created object to an EventBus's {@code register(Object)} method.
 *
 * This way, any object created by the container/factory/environment can
 * hook into the system's event model simply by exposing subscriber methods.
 *
 * <h3>What Event Bus problems can be detected at compile time?</h3>
 * Any problem that can be unambiguously detected by Java's type system.  For
 * example, defining a subscriber method for a nonexistent event type.
 *
 * <h3>What Event Bus problems can be detected immediately at registration?</h3>
 * Immediately upon invoking {@code register(Object)}, the listener being
 * registered is checked for the <i>well-formedness</i> of its subscriber methods.
 * Specifically, any methods marked with {@code @Subscribe} must take only a
 * single argument.
 *
 * Any violations of this rule will cause an {@code IllegalArgumentException}
 * to be thrown.
 *
 * (This check could be moved to compile-time using APT, a solution we're
 * researching.)
 *
 * <h3>What Event Bus problems may only be detected later, at runtime?</h3>
 * If a component posts events with no registered listeners, it <i>may</i>
 * indicate an error (typically an indication that you missed a
 * {@code @Subscribe} annotation, or that the listening component is not loaded).
 *
 * (Note that this is <i>not necessarily</i> indicative of a problem.  There
 * are many cases where an application will deliberately ignore a posted event,
 * particularly if the event is coming from code you don't control.)
 *
 * To handle such events, register a subscriber method for the {@code DeadEvent}
 * class.  Whenever EventBus receives an event with no registered subscribers, it
 * will turn it into a {@code DeadEvent} and pass it your way -- allowing you to
 * log it or otherwise recover.
 *
 * <h3>How do I test event listeners and their subscriber methods?</h3>
 * Because subscriber methods on your listener classes are normal methods, you can
 * simply call them from your test code to simulate the EventBus.
 */

NPE in IDEA plugin

I updated the pegdown-doclet plugin to 1.2, and after that I get the following NullPointerException when I open settings and choose "Pegdown doclet":

null
java.lang.NullPointerException
    at ch.raffael.doclets.pegdown.integrations.idea.PegdownDocletOptionsForm.<init>(PegdownDocletOptionsForm.java:86)
    at ch.raffael.doclets.pegdown.integrations.idea.PegdownConfigurable.createComponent(PegdownConfigurable.java:60)
    at com.intellij.openapi.options.ex.ConfigurableWrapper.createComponent(ConfigurableWrapper.java:162)
    at com.intellij.openapi.options.ex.ConfigurableCardPanel$1.compute(ConfigurableCardPanel.java:54)
    at com.intellij.openapi.options.ex.ConfigurableCardPanel$1.compute(ConfigurableCardPanel.java:51)
    at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:884)
    at com.intellij.openapi.options.ex.ConfigurableCardPanel.create(ConfigurableCardPanel.java:51)
    at com.intellij.openapi.options.newEditor.ConfigurableEditor$1.create(ConfigurableEditor.java:64)
    at com.intellij.openapi.options.newEditor.ConfigurableEditor$1.create(ConfigurableEditor.java:61)
    at com.intellij.ui.CardLayoutPanel.a(CardLayoutPanel.java:73)
    at com.intellij.ui.CardLayoutPanel.a(CardLayoutPanel.java:101)
    at com.intellij.ui.CardLayoutPanel.access$000(CardLayoutPanel.java:35)
    at com.intellij.ui.CardLayoutPanel$1$1.run(CardLayoutPanel.java:118)
    at com.intellij.openapi.application.impl.LaterInvocator$FlushQueue.run(LaterInvocator.java:332)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
    at com.intellij.ide.IdeEventQueue.e(IdeEventQueue.java:734)
    at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:569)
    at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:382)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:109)
    at java.awt.WaitDispatchSupport$2.run(WaitDispatchSupport.java:184)
    at java.awt.WaitDispatchSupport$4.run(WaitDispatchSupport.java:229)
    at java.awt.WaitDispatchSupport$4.run(WaitDispatchSupport.java:227)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.awt.WaitDispatchSupport.enter(WaitDispatchSupport.java:227)
    at java.awt.Dialog.show(Dialog.java:1084)
    at com.intellij.openapi.ui.impl.DialogWrapperPeerImpl$MyDialog.show(DialogWrapperPeerImpl.java:778)
    at com.intellij.openapi.ui.impl.DialogWrapperPeerImpl.show(DialogWrapperPeerImpl.java:465)
    at com.intellij.openapi.ui.DialogWrapper.invokeShow(DialogWrapper.java:1614)
    at com.intellij.openapi.ui.DialogWrapper.show(DialogWrapper.java:1571)
    at com.intellij.ide.actions.ShowSettingsUtilImpl.showSettingsDialog(ShowSettingsUtilImpl.java:114)
    at com.intellij.ide.actions.ShowSettingsAction.actionPerformed(ShowSettingsAction.java:65)
    at com.intellij.openapi.actionSystem.ex.ActionUtil.performActionDumbAware(ActionUtil.java:182)
    at com.intellij.openapi.actionSystem.impl.ActionMenuItem$ActionTransmitter$1.run(ActionMenuItem.java:312)
    at com.intellij.openapi.wm.impl.FocusManagerImpl.runOnOwnContext(FocusManagerImpl.java:958)
    at com.intellij.openapi.wm.impl.IdeFocusManagerImpl.runOnOwnContext(IdeFocusManagerImpl.java:124)
    at com.intellij.openapi.actionSystem.impl.ActionMenuItem$ActionTransmitter.actionPerformed(ActionMenuItem.java:282)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
    at com.intellij.openapi.actionSystem.impl.ActionMenuItem.fireActionPerformed(ActionMenuItem.java:109)
    at com.intellij.ui.plaf.beg.BegMenuItemUI.a(BegMenuItemUI.java:512)
    at com.intellij.ui.plaf.beg.BegMenuItemUI.access$300(BegMenuItemUI.java:44)
    at com.intellij.ui.plaf.beg.BegMenuItemUI$MyMouseInputHandler.mouseReleased(BegMenuItemUI.java:532)
    at java.awt.Component.processMouseEvent(Component.java:6525)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
    at java.awt.Component.processEvent(Component.java:6290)
    at java.awt.Container.processEvent(Container.java:2234)
    at java.awt.Component.dispatchEventImpl(Component.java:4881)
    at java.awt.Container.dispatchEventImpl(Container.java:2292)
    at java.awt.Component.dispatchEvent(Component.java:4703)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4898)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4533)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4462)
    at java.awt.Container.dispatchEventImpl(Container.java:2278)
    at java.awt.Window.dispatchEventImpl(Window.java:2750)
    at java.awt.Component.dispatchEvent(Component.java:4703)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:86)
    at java.awt.EventQueue$4.run(EventQueue.java:731)
    at java.awt.EventQueue$4.run(EventQueue.java:729)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
    at com.intellij.ide.IdeEventQueue.e(IdeEventQueue.java:734)
    at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:565)
    at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:382)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

The javadoc isn't rendered as markdown either, but that wasn't the case before the update either.

Add a {@toc} tag

For long docs (which are often found in package-info.java), it might be useful to provide a {@toc} tag that inserts a table of contents.

Error creating Javadoc

When processing my Java code with Pegdown, for one project I get the following exception and the generated documentation is incomplete (index files missing):

  [javadoc] java.lang.ClassCastException: com.sun.tools.javac.code.Type$AnnotatedType cannot be cast to com.sun.tools.javac.code.Type$ClassType
  [javadoc]     at com.sun.tools.javadoc.ParameterizedTypeImpl.parameterizedTypeToString(ParameterizedTypeImpl.java:140)
  [javadoc]     at com.sun.tools.javadoc.TypeMaker.getTypeString(TypeMaker.java:171)
  [javadoc]     at com.sun.tools.javadoc.ExecutableMemberDocImpl.makeSignature(ExecutableMemberDocImpl.java:247)
  [javadoc]     at com.sun.tools.javadoc.ExecutableMemberDocImpl.signature(ExecutableMemberDocImpl.java:228)
  [javadoc]     at com.sun.tools.doclets.internal.toolkit.util.VisibleMemberMap.getMemberKey(VisibleMemberMap.java:763)
  [javadoc]     at com.sun.tools.doclets.internal.toolkit.util.VisibleMemberMap.access$1000(VisibleMemberMap.java:49)
  [javadoc]     at com.sun.tools.doclets.internal.toolkit.util.VisibleMemberMap$ClassMembers.isOverridden(VisibleMemberMap.java:520)
  [javadoc]     at com.sun.tools.doclets.internal.toolkit.util.VisibleMemberMap$ClassMembers.addMembers(VisibleMemberMap.java:378)
  [javadoc]     at com.sun.tools.doclets.internal.toolkit.util.VisibleMemberMap$ClassMembers.build(VisibleMemberMap.java:339)
  [javadoc]     at com.sun.tools.doclets.internal.toolkit.util.VisibleMemberMap$ClassMembers.access$100(VisibleMemberMap.java:291)
  [javadoc]     at com.sun.tools.doclets.internal.toolkit.util.VisibleMemberMap.<init>(VisibleMemberMap.java:127)
  [javadoc]     at com.sun.tools.doclets.internal.toolkit.builders.MemberSummaryBuilder.<init>(MemberSummaryBuilder.java:82)
  [javadoc]     at com.sun.tools.doclets.internal.toolkit.builders.MemberSummaryBuilder.getInstance(MemberSummaryBuilder.java:101)
  [javadoc]     at com.sun.tools.doclets.internal.toolkit.builders.BuilderFactory.getMemberSummaryBuilder(BuilderFactory.java:278)
  [javadoc]     at com.sun.tools.doclets.formats.html.ClassWriterImpl.getNavSummaryLinks(ClassWriterImpl.java:641)
  [javadoc]     at com.sun.tools.doclets.formats.html.ClassWriterImpl.addSummaryDetailLinks(ClassWriterImpl.java:622)
  [javadoc]     at com.sun.tools.doclets.formats.html.HtmlDocletWriter.addNavLinks(HtmlDocletWriter.java:560)
  [javadoc]     at com.sun.tools.doclets.formats.html.ClassWriterImpl.getHeader(ClassWriterImpl.java:165)
  [javadoc]     at com.sun.tools.doclets.internal.toolkit.builders.ClassBuilder.buildClassDoc(ClassBuilder.java:145)
  [javadoc]     at sun.reflect.GeneratedMethodAccessor11.invoke(Unknown Source)
  [javadoc]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  [javadoc]     at java.lang.reflect.Method.invoke(Method.java:498)
  [javadoc]     at com.sun.tools.doclets.internal.toolkit.builders.AbstractBuilder.invokeMethod(AbstractBuilder.java:180)
  [javadoc]     at com.sun.tools.doclets.internal.toolkit.builders.AbstractBuilder.build(AbstractBuilder.java:135)
  [javadoc]     at com.sun.tools.doclets.internal.toolkit.builders.ClassBuilder.build(ClassBuilder.java:120)
  [javadoc]     at com.sun.tools.doclets.formats.html.HtmlDoclet.generateClassFiles(HtmlDoclet.java:189)
  [javadoc]     at com.sun.tools.doclets.internal.toolkit.AbstractDoclet.generateClassFiles(AbstractDoclet.java:192)
  [javadoc]     at com.sun.tools.doclets.internal.toolkit.AbstractDoclet.startGeneration(AbstractDoclet.java:137)
  [javadoc]     at com.sun.tools.doclets.internal.toolkit.AbstractDoclet.start(AbstractDoclet.java:82)
  [javadoc]     at com.sun.tools.doclets.formats.html.HtmlDoclet.start(HtmlDoclet.java:80)
  [javadoc]     at com.sun.tools.doclets.standard.Standard.start(Standard.java:39)
  [javadoc]     at ch.raffael.doclets.pegdown.PegdownDoclet.start(PegdownDoclet.java:155)
  [javadoc]     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  [javadoc]     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  [javadoc]     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  [javadoc]     at java.lang.reflect.Method.invoke(Method.java:498)
  [javadoc]     at com.sun.tools.javadoc.DocletInvoker.invoke(DocletInvoker.java:310)
  [javadoc]     at com.sun.tools.javadoc.DocletInvoker.start(DocletInvoker.java:189)
  [javadoc]     at com.sun.tools.javadoc.Start.parseAndExecute(Start.java:366)
  [javadoc]     at com.sun.tools.javadoc.Start.begin(Start.java:219)
  [javadoc]     at com.sun.tools.javadoc.Start.begin(Start.java:205)
  [javadoc]     at com.sun.tools.javadoc.Main.execute(Main.java:64)
  [javadoc]     at com.sun.tools.javadoc.Main.main(Main.java:54)

Happens in 1.2.1 and 1.3

IDEA plugin fails

I'm using

IntelliJ IDEA 2016.1.2
Build #IU-145.972, built on May 14, 2016
JRE: 1.8.0_76-release-b162 x86_64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o

See stack trace:

Assertion failed
java.lang.Throwable
    at com.intellij.openapi.diagnostic.Logger.assertTrue(Logger.java:156)
    at com.intellij.openapi.diagnostic.Logger.assertTrue(Logger.java:165)
    at com.intellij.psi.impl.source.PsiParameterListImpl.getParameterIndex(PsiParameterListImpl.java:50)
    at com.intellij.psi.util.PsiFormatUtil.getExternalName(PsiFormatUtil.java:446)
    at com.intellij.codeInsight.BaseExternalAnnotationsManager.getExternalName(BaseExternalAnnotationsManager.java:80)
    at com.intellij.codeInsight.BaseExternalAnnotationsManager.a(BaseExternalAnnotationsManager.java:208)
    at com.intellij.codeInsight.BaseExternalAnnotationsManager.a(BaseExternalAnnotationsManager.java:146)
    at com.intellij.codeInsight.BaseExternalAnnotationsManager.findExternalAnnotations(BaseExternalAnnotationsManager.java:123)
    at com.intellij.codeInsight.javadoc.JavaDocInfoGenerator.a(JavaDocInfoGenerator.java:918)
    at com.intellij.codeInsight.javadoc.JavaDocInfoGenerator.a(JavaDocInfoGenerator.java:1058)
    at com.intellij.codeInsight.javadoc.JavaDocInfoGenerator.generateDocInfoCore(JavaDocInfoGenerator.java:396)
    at com.intellij.codeInsight.javadoc.JavaDocInfoGenerator.generateDocInfo(JavaDocInfoGenerator.java:437)
    at com.intellij.lang.java.JavaDocumentationProvider.generateExternalJavadoc(JavaDocumentationProvider.java:554)
    at com.intellij.lang.java.JavaDocumentationProvider.generateDoc(JavaDocumentationProvider.java:542)
    > at  ch.raffael.doclets.pegdown.integrations.idea.PegdownDocumentationProvider.generateDoc(PegdownDocumentationProvider.java:134)
    at com.intellij.lang.documentation.CompositeDocumentationProvider.generateDoc(CompositeDocumentationProvider.java:144)
    at com.intellij.codeInsight.navigation.CtrlMouseHandler$9$1.run(CtrlMouseHandler.java:666)
    at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:950)
    at com.intellij.codeInsight.navigation.CtrlMouseHandler$9.run(CtrlMouseHandler.java:661)
    at com.intellij.util.concurrency.QueueProcessor.runSafely(QueueProcessor.java:238)
    at com.intellij.util.Alarm$Request$1.run(Alarm.java:378)
    at com.intellij.util.Alarm$Request.run(Alarm.java:389)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at com.intellij.util.concurrency.SchedulingWrapper$MyScheduledFutureTask.run(SchedulingWrapper.java:227)
    at com.intellij.util.concurrency.BoundedTaskExecutor$2.run(BoundedTaskExecutor.java:187)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

Exception with IDEA plugin

I'm not really sure what happened and I'm unable to reproduce it, but I got this from IntelliJ when I closed a file:

Argument for @NotNull parameter 'file' of com/intellij/openapi/roots/impl/ProjectFileIndexImpl.getModuleForFile must not be null
java.lang.IllegalArgumentException: Argument for @NotNull parameter 'file' of com/intellij/openapi/roots/impl/ProjectFileIndexImpl.getModuleForFile must not be null
    at com.intellij.openapi.roots.impl.ProjectFileIndexImpl.getModuleForFile(ProjectFileIndexImpl.java)
    at ch.raffael.doclets.pegdown.integrations.idea.DocCommentProcessor.<init>(DocCommentProcessor.java:93)
    at ch.raffael.doclets.pegdown.integrations.idea.PegdownDocumentationProvider.generateDoc(PegdownDocumentationProvider.java:128)
    at com.intellij.lang.documentation.CompositeDocumentationProvider.generateDoc(CompositeDocumentationProvider.java:134)
    at com.intellij.codeInsight.navigation.CtrlMouseHandler$9$1.run(CtrlMouseHandler.java:647)
    at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:872)
    at com.intellij.codeInsight.navigation.CtrlMouseHandler$9.run(CtrlMouseHandler.java:643)
    at com.intellij.util.concurrency.QueueProcessor.runSafely(QueueProcessor.java:238)
    at com.intellij.util.Alarm$Request$1.run(Alarm.java:351)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at com.intellij.util.concurrency.QueueProcessor$RunnableConsumer.consume(QueueProcessor.java:298)
    at com.intellij.util.concurrency.QueueProcessor$RunnableConsumer.consume(QueueProcessor.java:295)
    at com.intellij.util.concurrency.QueueProcessor$2$1.run(QueueProcessor.java:110)
    at com.intellij.util.concurrency.QueueProcessor.runSafely(QueueProcessor.java:238)
    at com.intellij.util.concurrency.QueueProcessor$2.consume(QueueProcessor.java:107)
    at com.intellij.util.concurrency.QueueProcessor$2.consume(QueueProcessor.java:104)
    at com.intellij.util.concurrency.QueueProcessor$3$1.run(QueueProcessor.java:215)
    at com.intellij.util.concurrency.QueueProcessor.runSafely(QueueProcessor.java:238)
    at com.intellij.util.concurrency.QueueProcessor$3.run(QueueProcessor.java:212)
    at com.intellij.openapi.application.impl.ApplicationImpl$8.run(ApplicationImpl.java:400)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
    at org.jetbrains.ide.PooledThreadExecutor$1$1.run(PooledThreadExecutor.java:56)

plugin doesn't render in IntelliJ 14 started with Java 7 on OSX

While trying to use the plugin in IntelliJ 14.3, I could not make it render Quick Documentation even after the following steps:

  • plugin couldn't load in OSX by default because IntelliJ launches using Java 1.6
  • after setting JRE for IntelliJ to 1.6+ instead of 1.6*, it launched using the latest installed JRE, which was Java 8 => got 3 NullPointerException in the logs
  • I then set IntelliJ to launch with Java 7 (1.7*) => no visible errors, activated the plugin in preferences

Once I got it to load without noticeable error, I tried to add markdown formatting (** for bold) and show the Quick Documentation popup, the javadoc's markdown wasn't rendered.

Is there any known compatibility issue with IntelliJ 14? Maybe a workaround that worked previously and now doesn't?

Escape '@' in code blocks

When creating a code block, '@' characters should be translated into {@literal @}, so they are not interpreted as javadoc tags.

h2 in class descriptions

Too much space below, too little above.

Add a new CSS rule for .block h2. Make sure it looks the same in package-info.java (the issue isn't present there).

Can't reference diagrams defined in other comment blocks

I had a large diagram defined at the class level, then inserted it into a method comment. Pegdown generated the javadoc as expected, the diagram was shown twice. The intellij idea integration however shows a broken image link in the method.

maven hangs for 10+ seconds on exit

It seems that the doclet has some weird behavior on maven shutdown. Even a mvn clean hangs for more than 10 seconds after it reports build success. The problem goes away after I comment the plugin config in my pom.xml.

          <plugin>
                <artifactId>maven-javadoc-plugin</artifactId>
                <configuration>
                    <doclet>ch.raffael.doclets.pegdown.PegdownDoclet</doclet>
                    <docletArtifact>
                        <groupId>ch.raffael.pegdown-doclet</groupId>
                        <artifactId>pegdown-doclet</artifactId>
                        <version>1.1</version>
                    </docletArtifact>
                    <useStandardDocletOptions>true</useStandardDocletOptions>
                </configuration>
            </plugin>

Generate TODO-Titles as HTML

Generate the title and number into the HTML instead of leaving that to CSS. While using CSS has the advantage of being more customisable, JavaDocs should be viewable with simple browsers that don't support the more sophisticated CSS features (e.g. QuickDoc in IDEA).

.jar file

README.md has under section Invoking:
javadoc -doclet ch.raffael.doclets.pegdown.PegdownDoclet -docletpath /path/to/pegdown-doclet-1.1-all.jar

When I download pegdown-doclet by clicking the Download ZIP button, however, I don't see a pegdown-doclet-1.1-all.jar (or other .jar) file. Why? Why no other installation instructions?

thank you,
George H

org/parboiled/errors/ParserRuntimeException

Hi,
I'm completely new to javadocs and am trying to use the pegdown-doclet plugin. When I run javadocs like:
JAVA_HOME=/usr/libexec/java_home /Library/Java/JavaVirtualMachines/jdk1.7.0_60.jdk/Contents/Home/bin/javadoc -d javadoc/
-sourcepath ~/path/to/my/src/
-doclet ch.raffael.doclets.pegdown.PegdownDoclet
-docletpath /path/to/download/and/then/pegdown-doclet-master/target/classes/
com.fully.qualified.name.of.my.package

I get the following error:
java.lang.NoClassDefFoundError: org/parboiled/errors/ParserRuntimeException
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2570)
at java.lang.Class.getMethod0(Class.java:2813)
at java.lang.Class.getMethod(Class.java:1663)
at com.sun.tools.javadoc.DocletInvoker.invoke(DocletInvoker.java:257)
at com.sun.tools.javadoc.DocletInvoker.optionLength(DocletInvoker.java:184)
at com.sun.tools.javadoc.Start.parseAndExecute(Start.java:347)
at com.sun.tools.javadoc.Start.begin(Start.java:167)
at com.sun.tools.javadoc.Main.execute(Main.java:59)
at com.sun.tools.javadoc.Main.main(Main.java:49)
Caused by: java.lang.ClassNotFoundException: org.parboiled.errors.ParserRuntimeException
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
... 10 more
javadoc: error - fatal error
1 error

I am running on Mac OSX and built the plugin by running mvn install. My maven version is:
JAVA_HOME=/usr/libexec/java_home mvn -version
Apache Maven 3.0.5 (r01de14724cdef164cd33c7c8c2fe155faf9602da; 2013-02-19 13:51:28+0000)
Maven home: /opt/local/share/java/maven3
Java version: 1.7.0_60, vendor: Oracle Corporation
Java home: /Library/Java/JavaVirtualMachines/jdk1.7.0_60.jdk/Contents/Home/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "mac os x", version: "10.9.3", arch: "x86_64", family: "mac"

Sorry, I'm probably missing something basic.

Thanks in advance, Jim

1.1.2 release

any chance you could cut a 1.1.2 release? the java8 support would be great.

Handling of headings in doc comments

Change rendering of headings: Render h1 as h3, h2 as h4, etc. This probably makes much more sense than not using h1 at all and starting with h2 in doc comments (as I currently do). Have a closer look at how hX elements are currently used by the standard doclet and the API documentation, and how we best fit in with headings in the doc comments. Alternatively, just adapt the CSS.

Note: This may break compatibility with older versions.

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.