Add initial javascript support with jsdoc 3.
parent
b0c4a8870c
commit
9bc6072283
@ -1,3 +1,4 @@
|
||||
from .dotnet import DotNetDomain
|
||||
from .python import PythonDomain
|
||||
from .go import GoDomain
|
||||
from .go import GoDomain
|
||||
from .javascript import JavaScriptDomain
|
@ -0,0 +1,201 @@
|
||||
import os
|
||||
import json
|
||||
import subprocess
|
||||
|
||||
from sphinx.util.osutil import ensuredir
|
||||
|
||||
from .base import AutoAPIBase, AutoAPIDomain
|
||||
from ..settings import env
|
||||
|
||||
|
||||
class JavaScriptDomain(AutoAPIDomain):
|
||||
|
||||
'''Auto API domain handler for Javascript
|
||||
|
||||
Parses directly from Javascript files.
|
||||
|
||||
:param app: Sphinx application passed in as part of the extension
|
||||
'''
|
||||
|
||||
def create_class(self, data):
|
||||
'''Return instance of class based on Javascript data
|
||||
|
||||
Data keys handled here:
|
||||
|
||||
type
|
||||
Set the object class
|
||||
|
||||
consts, types, vars, funcs
|
||||
Recurse into :py:meth:`create_class` to create child object
|
||||
instances
|
||||
|
||||
:param data: dictionary data from godocjson output
|
||||
'''
|
||||
obj_map = dict(
|
||||
(cls.type, cls) for cls
|
||||
in ALL_CLASSES
|
||||
)
|
||||
try:
|
||||
cls = obj_map[data['kind']]
|
||||
except KeyError:
|
||||
self.app.warn('Unknown Type: %s' % data)
|
||||
else:
|
||||
# Recurse for children
|
||||
obj = cls(data)
|
||||
if 'children' in data:
|
||||
for child_data in data['children']:
|
||||
for child_obj in self.create_class(child_data):
|
||||
obj.children.append(child_obj)
|
||||
yield obj
|
||||
|
||||
def read_file(self, path, **kwargs):
|
||||
'''Read file input into memory, returning deserialized objects
|
||||
|
||||
:param path: Path of file to read
|
||||
'''
|
||||
# TODO support JSON here
|
||||
# TODO sphinx way of reporting errors in logs?
|
||||
|
||||
try:
|
||||
parsed_data = json.loads(subprocess.check_output(['jsdoc', '-X', path]))
|
||||
return parsed_data
|
||||
except IOError:
|
||||
print Warning('Error reading file: {0}'.format(path))
|
||||
except TypeError:
|
||||
print Warning('Error reading file: {0}'.format(path))
|
||||
return None
|
||||
|
||||
def get_objects(self, pattern, format='yaml'):
|
||||
'''Trigger find of serialized sources and build objects'''
|
||||
for path in self.find_files(pattern):
|
||||
data = self.read_file(path, format=format)
|
||||
if data:
|
||||
# Returns a list of objects
|
||||
for item in data:
|
||||
for obj in self.create_class(item):
|
||||
self.add_object(obj)
|
||||
|
||||
def full(self):
|
||||
self.get_objects(self.get_config('autoapi_file_pattern'), format='json')
|
||||
self.generate_output()
|
||||
self.write_indexes()
|
||||
|
||||
def generate_output(self):
|
||||
for obj in self.app.env.autoapi_data:
|
||||
|
||||
if not obj:
|
||||
continue
|
||||
|
||||
rst = obj.render()
|
||||
# Detail
|
||||
try:
|
||||
filename = obj.name.split('(')[0]
|
||||
except IndexError:
|
||||
filename = obj.name
|
||||
detail_dir = os.path.join(self.get_config('autoapi_root'),
|
||||
*filename.split('.'))
|
||||
ensuredir(detail_dir)
|
||||
# TODO: Better way to determine suffix?
|
||||
path = os.path.join(detail_dir, '%s%s' % ('index', self.get_config('source_suffix')[0]))
|
||||
if rst:
|
||||
with open(path, 'w+') as detail_file:
|
||||
detail_file.write(rst.encode('utf-8'))
|
||||
|
||||
def write_indexes(self):
|
||||
# Write Index
|
||||
top_level_index = os.path.join(self.get_config('autoapi_root'),
|
||||
'index.rst')
|
||||
with open(top_level_index, 'w+') as top_level_file:
|
||||
content = env.get_template('index.rst')
|
||||
top_level_file.write(content.render())
|
||||
|
||||
|
||||
class JavaScriptBase(AutoAPIBase):
|
||||
|
||||
language = 'javascript'
|
||||
|
||||
def __init__(self, obj):
|
||||
super(JavaScriptBase, self).__init__(obj)
|
||||
self.name = obj.get('name')
|
||||
self.id = self.name
|
||||
|
||||
# Second level
|
||||
self.docstring = obj.get('description', '')
|
||||
#self.docstring = obj.get('comment', '')
|
||||
|
||||
self.imports = obj.get('imports', [])
|
||||
self.children = []
|
||||
self.parameters = map(
|
||||
lambda n: {'name': n['name'],
|
||||
'type': n['type'][0]},
|
||||
obj.get('param', [])
|
||||
)
|
||||
|
||||
# Language Specific
|
||||
pass
|
||||
|
||||
def __str__(self):
|
||||
return '<{cls} {id}>'.format(cls=self.__class__.__name__,
|
||||
id=self.id)
|
||||
|
||||
@property
|
||||
def short_name(self):
|
||||
'''Shorten name property'''
|
||||
return self.name.split('.')[-1]
|
||||
|
||||
@property
|
||||
def namespace(self):
|
||||
pieces = self.id.split('.')[:-1]
|
||||
if pieces:
|
||||
return '.'.join(pieces)
|
||||
|
||||
@property
|
||||
def ref_type(self):
|
||||
return self.type
|
||||
|
||||
@property
|
||||
def ref_directive(self):
|
||||
return self.type
|
||||
|
||||
@property
|
||||
def methods(self):
|
||||
return self.obj.get('methods', [])
|
||||
|
||||
def __lt__(self, other):
|
||||
'''Sort object by name'''
|
||||
if isinstance(other, JavaScriptBase):
|
||||
return self.name.lower() < other.name.lower()
|
||||
return self.name < other
|
||||
|
||||
|
||||
class JavaScriptClass(JavaScriptBase):
|
||||
type = 'class'
|
||||
ref_directive = 'class'
|
||||
|
||||
|
||||
class JavaScriptFunction(JavaScriptBase):
|
||||
type = 'function'
|
||||
ref_type = 'func'
|
||||
|
||||
|
||||
class JavaScriptData(JavaScriptBase):
|
||||
type = 'data'
|
||||
ref_directive = 'data'
|
||||
|
||||
|
||||
class JavaScriptMember(JavaScriptBase):
|
||||
type = 'member'
|
||||
ref_directive = 'member'
|
||||
|
||||
|
||||
class JavaScriptAttribute(JavaScriptBase):
|
||||
type = 'attribute'
|
||||
ref_directive = 'attr'
|
||||
|
||||
ALL_CLASSES = [
|
||||
JavaScriptFunction,
|
||||
JavaScriptClass,
|
||||
JavaScriptData,
|
||||
JavaScriptAttribute,
|
||||
JavaScriptMember,
|
||||
]
|
@ -0,0 +1,20 @@
|
||||
.. js:class:: {{ obj.name }}{% if obj.args %}({{ obj.args|join(',') }}){% endif %}
|
||||
|
||||
{% if obj.docstring %}
|
||||
|
||||
.. rubric:: Summary
|
||||
|
||||
{{ obj.docstring|indent(3) }}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if obj.methods %}
|
||||
|
||||
{% for method in obj.methods %}
|
||||
|
||||
{% macro render() %}{{ method.render() }}{% endmacro %}
|
||||
{{ render()|indent(3) }}
|
||||
|
||||
{%- endfor %}
|
||||
|
||||
{% endif %}
|
@ -0,0 +1,14 @@
|
||||
{# Identention in this file is important #}
|
||||
|
||||
{% if is_method %}
|
||||
{# Slice self off #}
|
||||
.. method:: {{ obj.name.split('.')[-1] }}({{ args[1:]|join(',') }})
|
||||
{% else %}
|
||||
.. function:: {{ obj.name.split('.')[-1] }}({{ args|join(',') }})
|
||||
{% endif %}
|
||||
|
||||
{% if obj.docstring %}
|
||||
{{ obj.docstring|indent(3) }}
|
||||
{% endif %}
|
||||
|
||||
|
@ -0,0 +1,7 @@
|
||||
{# Identention in this file is important #}
|
||||
|
||||
.. {{ obj.type }}:: {{ obj.name }}
|
||||
|
||||
{{ obj.docstring|indent(3) }}
|
||||
|
||||
|
@ -0,0 +1,52 @@
|
||||
{{ obj.name }}
|
||||
{{ "-" * obj.name|length }}
|
||||
|
||||
{% block toc %}
|
||||
|
||||
{% if obj.children %}
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
{% for item in obj.children|sort %}
|
||||
/autoapi/{{ item.id.split('.')|join('/') }}/index
|
||||
{%- endfor %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% if obj.docstring %}
|
||||
|
||||
.. rubric:: Summary
|
||||
|
||||
{{ obj.docstring }}
|
||||
|
||||
{% endif %}
|
||||
|
||||
.. js:module:: {{ obj.name }}
|
||||
|
||||
|
||||
|
||||
{% block content %}
|
||||
|
||||
{%- macro display_type(item_type) %}
|
||||
|
||||
{{ item_type.title() }}
|
||||
{{ "*" * item_type|length }}
|
||||
|
||||
{%- for obj_item in obj.item_map.get(item_type, []) %}
|
||||
{% macro render() %}{{ obj_item.render() }}{% endmacro %}
|
||||
|
||||
{{ render()|indent(4) }}
|
||||
|
||||
{%- endfor %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- for item_type in obj.item_map.keys() %}
|
||||
{% if item_type.lower() != 'module' %}
|
||||
{{ display_type(item_type) }}
|
||||
{% endif %}
|
||||
{%- endfor %}
|
||||
|
||||
{% endblock %}
|
@ -0,0 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
templates_path = ['_templates']
|
||||
source_suffix = '.rst'
|
||||
master_doc = 'index'
|
||||
project = u'jsexample'
|
||||
copyright = u'2015, rtfd'
|
||||
author = u'rtfd'
|
||||
version = '0.1'
|
||||
release = '0.1'
|
||||
language = None
|
||||
exclude_patterns = ['_build']
|
||||
pygments_style = 'sphinx'
|
||||
todo_include_todos = False
|
||||
html_theme = 'alabaster'
|
||||
html_static_path = ['_static']
|
||||
htmlhelp_basename = 'jsexampledoc'
|
||||
extensions = ['autoapi.extension']
|
||||
autoapi_type = 'javascript'
|
||||
autoapi_dir = 'example'
|
||||
autoapi_file_pattern = '*.js'
|
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Creates an instance of Circle.
|
||||
*
|
||||
* @constructor
|
||||
* @this {Circle}
|
||||
* @param {number} r The desired radius of the circle.
|
||||
*/
|
||||
function Circle(r) {
|
||||
/** @private */ this.radius = r;
|
||||
/** @private */ this.circumference = 2 * Math.PI * r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Circle from a diameter.
|
||||
*
|
||||
* @param {number} d The desired diameter of the circle.
|
||||
* @return {Circle} The new Circle object.
|
||||
*/
|
||||
Circle.fromDiameter = function (d) {
|
||||
return new Circle(d / 2);
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the circumference of the Circle.
|
||||
*
|
||||
* @deprecated
|
||||
* @this {Circle}
|
||||
* @return {number} The circumference of the circle.
|
||||
*/
|
||||
Circle.prototype.calculateCircumference = function () {
|
||||
return 2 * Math.PI * this.radius;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the pre-computed circumference of the Circle.
|
||||
*
|
||||
* @this {Circle}
|
||||
* @return {number} The circumference of the circle.
|
||||
*/
|
||||
Circle.prototype.getCircumference = function () {
|
||||
return this.circumference;
|
||||
};
|
||||
|
||||
/**
|
||||
* Find a String representation of the Circle.
|
||||
*
|
||||
* @override
|
||||
* @this {Circle}
|
||||
* @return {string} Human-readable representation of this Circle.
|
||||
*/
|
||||
Circle.prototype.toString = function () {
|
||||
return "A Circle object with radius of " + this.radius + ".";
|
||||
};
|
@ -0,0 +1,21 @@
|
||||
Welcome to jsexample's documentation!
|
||||
=====================================
|
||||
|
||||
.. toctree::
|
||||
|
||||
autoapi/index
|
||||
|
||||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
|
Loading…
Reference in New Issue