From be911d482592f7bd6e5246649cc59de0b0f589ab Mon Sep 17 00:00:00 2001 From: kgalli Date: Thu, 26 Feb 2015 12:05:18 +0000 Subject: [PATCH 1/2] Add aglio template layout files --- doc/api_documentation_layouts/README.md | 48 ++++ .../openproject-includes.jade | 261 ++++++++++++++++++ .../openproject-layout.jade | 190 +++++++++++++ 3 files changed, 499 insertions(+) create mode 100644 doc/api_documentation_layouts/README.md create mode 100644 doc/api_documentation_layouts/openproject-includes.jade create mode 100644 doc/api_documentation_layouts/openproject-layout.jade diff --git a/doc/api_documentation_layouts/README.md b/doc/api_documentation_layouts/README.md new file mode 100644 index 000000000000..caa1471c12a2 --- /dev/null +++ b/doc/api_documentation_layouts/README.md @@ -0,0 +1,48 @@ + + +API Documentation Layouts +------------------------- + +## API Version 3 + +_Status: under development_ + +The documentation for APIv3 is written in the [API Blueprint Format](http://apiblueprint.org/). + +You can use [aglio](https://github.com/danielgtaylor/aglio) to generate HTML documentation. +Aglio supports the use of templates to adjust the ouput to your own needs. OpenProject is +using the openproject.jade template file. To generate the documentation using the +openproject.jade layout file the following command: + +```bash +aglio -t openproject-layout.jade -i ../apiv3-documentation.api -o api.html + +``` + diff --git a/doc/api_documentation_layouts/openproject-includes.jade b/doc/api_documentation_layouts/openproject-includes.jade new file mode 100644 index 000000000000..4efae4868ccf --- /dev/null +++ b/doc/api_documentation_layouts/openproject-includes.jade @@ -0,0 +1,261 @@ +//- Common mixins that templates can share + +mixin Nav(multipage, collapsible) + div.col-md-3 + ul.menu(id="op-api-menu") + - var menuItem = 'menu-item'; + each resourceGroup in api.resourceGroups + + - var randomGroupIndex = Math.random().toString(16).slice(2) + - var groupHasChildren = resourceGroup.resources.length ? menuItem + '-has-children' : '' + - var resourceGroupClasses = [menuItem, menuItem + '-type-post_type', menuItem + '-object-page', 'dropdown', menuItem + '-' + randomGroupIndex, groupHasChildren] + + li(class=resourceGroupClasses, id=[menuItem + '-' + randomGroupIndex]) + a.menu-item-link(href="##{slug(resourceGroup.name)}") + = resourceGroup.name || 'Resource Group' + if resourceGroup.resources.length + a.dropdown-toggle.toggle-open-menu(href="##{slug(resourceGroup.name)}", data-toggle="dropdown") + i.icon.icon-arrow-right5-2 + i.icon.icon-arrow-right5-3 + ul.dropdown-menu + each resource in resourceGroup.resources + - var randomResourceIndex = Math.random().toString(16).slice(2) + - var resourceHasChildren = resource.length ? menuItem + '-has-children' : '' + - var resourceClasses = [menuItem, menuItem + '-type-post_type', menuItem + '-object-page', 'dropdown', menuItem + '-' + randomResourceIndex, resourceHasChildren] + li(class=resourceClasses, id=[menuItem + '-' + randomResourceIndex]) + a.menu-item-link(href="##{slug(resourceGroup.name)}-#{slug(resource.name)}") + = resource.name || 'Resource' + if (resource.actions.length != 1) + a.dropdown-toggle.toggle-open-menu(href="##{slug(resourceGroup.name)}-#{slug(resource.name)}", data-toggle="dropdown") + i.icon.icon-arrow-right5-2 + i.icon.icon-arrow-right5-3 + ul.dropdown-menu + each action in resource.actions + - var randomActionIndex = Math.random().toString(16).slice(2) + - var resourceActionClasses = [menuItem, menuItem + '-type-post_type', menuItem + '-object-page', 'dropdown', menuItem + '-' + randomActionIndex] + li(class=resourceActionClasses, id=[menuItem + '-' + randomActionIndex]) + a.menu-item-link(href="##{slug(resourceGroup.name)}-#{slug(resource.name)}-#{slug(action.method)}") + = action.name || action.method + ' ' + resource.uriTemplate + else + each meta in api.metadata + if meta.name == 'HOST' + p(style="text-align: center; word-wrap: break-word;") + a(href=meta.value)= meta.value + +mixin Parameters(params) + ul.list-group + li.list-group-item.bg-default: strong Parameters + li.list-group-item + dl.dl-horizontal + each param in params + dt= param.name + dd + code= param.type + |   + if param.required + span.required (required) + else + span (optional) + |   + if param.default + span.text-info.default + strong Default:  + span= param.default + |   + if param.example + span.text-muted.example + strong Example:  + span= param.example + != markdown(param.description) + if param.values.length + p + strong Choices:  + each value in param.values + code= value.value + = ' ' + +mixin RequestResponse(title, request, resourceGroup, resource, action) + - var id = hash(resourceGroup.name.toString() + resource.name.toString() + action.name.toString() + action.method.toString() + title.toString() + request.name.toString() + request.headers.toString() + request.body.toString() + request.schema.toString()) + - var content = request.description || Object.keys(request.headers).length || request.body || request.schema + li.list-group-item + strong + = title + if request.name + |    + code= request.name + if content + a.pull-right.collapsed(data-toggle="collapse", data-target="##{id}") + span.closed Show + span.open Hide + if content + li.list-group-item.panel-collapse.collapse(id=id) + if request.description + .description!= markdown(request.description) + + if Object.keys(request.headers).length + h5 Headers + pre + code + each item in request.headers + != highlight(item.name + ': ' + item.value, 'http') + br + if request.body + h5 Body + pre + code!= highlight(request.body) + if request.schema + h5 Schema + pre + code!= highlight(request.schema) + + +mixin Examples(resourceGroup, resource, action) + ul.list-group + each example in action.examples + each request in example.requests + +RequestResponse('Request', request, resourceGroup, resource, action) + each response in example.responses + +RequestResponse('Response', response, resourceGroup, resource, action) + +mixin ResourceGroup(resourceGroup, getButtonClass, multipage) + .panel.panel-default + .panel-heading + h3(id="#{slug(resourceGroup.name)}") + = resourceGroup.name || 'Resource Group' + |   + a(href="##{multipage ? 'page:' : ''}#{slug(resourceGroup.name)}") + i.fa.fa-link + .panel-body + if resourceGroup.description + != markdown(resourceGroup.description) + each resource in resourceGroup.resources + h4(id="#{slug(resourceGroup.name)}-#{slug(resource.name)}") + = resource.name || 'Resources' + |   + a(href="##{(multipage ? 'page:' + slug(resourceGroup.name) + ',header:' : '')}#{slug(resourceGroup.name)}-#{slug(resource.name)}") + i.fa.fa-link + if resource.description + != markdown(resource.description) + each action in resource.actions + case action.method + when 'POST': - var panelClass = 'panel-success' + when 'GET': - var panelClass = 'panel-info' + when 'PUT': - var panelClass = 'panel-warning' + when 'PATCH': - var panelClass = 'panel-warning' + when 'DELETE': - var panelClass = 'panel-danger' + default: - var panelClass = 'panel-default' + section.panel(class=panelClass, id="#{slug(resourceGroup.name)}-#{slug(resource.name)}-#{slug(action.method)}") + .panel-heading + if action.name + div(style="float:right") + span(style="text-transform: lowercase")= action.name + case action.method + when 'POST': - var btnClass = 'btn-success' + when 'GET': - var btnClass = 'btn-' + getButtonClass + when 'PUT': - var btnClass = 'btn-warning' + when 'PATCH': - var btnClass = 'btn-warning' + when 'DELETE': - var btnClass = 'btn-danger' + default: - var btnClass = 'btn-default' + div(style="float:left") + a.btn.btn-xs(class=btnClass, href="##{(multipage ? 'page:' + slug(resourceGroup.name) + ',header:' : '')}#{slug(resourceGroup.name)}-#{slug(resource.name)}-#{slug(action.method)}")= action.method + div(style="overflow:hidden" class="panel-heading-code") + code= resource.uriTemplate + if action.description + .panel-body!= markdown(action.description) + + - var params = action.parameters.length ? action.parameters : resource.parameters + if params.length + +Parameters(params) + if action.examples + +Examples(resourceGroup, resource, action) + +mixin Paginate(resourceGroups, index) + if index < resourceGroups.length - 1 + a.btn.btn-default.pull-right(href="#page:#{slug(resourceGroups[index + 1].name)}") + | Next  + i.fa.fa-arrow-circle-right + + if index > 0 + a.btn.btn-default(href="#page:#{slug(resourceGroups[index - 1].name)}") + i.fa.fa-arrow-circle-left + | Previous + else + a.btn.btn-default(href="#") + i.fa.fa-arrow-circle-left + | Previous + .clearfix + hr + +mixin Icon(method) + case method + when 'GET' + span.badge.alert-info + i.fa.fa-arrow-down + when 'POST' + span.badge.alert-success + i.fa.fa-plus + when 'PUT' + span.badge.alert-warning + i.fa.fa-pencil + when 'PATCH' + span.badge.alert-warning + i.fa.fa-pencil + when 'DELETE' + span.badge.alert-danger + i.fa.fa-times + default + span.badge + i.fa.fa-dot-circle-o + +mixin Content(getButtonClass, multipage) + div(data-bind=multipage ? "visible: page() == 'home'" : undefined) + header + .page-header + h1#top= api.name || 'API Documentation' + + .description!= markdown(api.description) + + if multipage + a.btn.btn-default.pull-right(href="#page:#{slug(api.resourceGroups[0].name)}") + | Next  + i.fa.fa-arrow-circle-right + .clearfix + hr + + each resourceGroup, index in api.resourceGroups + div(data-bind=multipage ? "visible: page() == '#{slug(resourceGroup.name)}', style: {marginTop: page() == '#{slug(resourceGroup.name)}' ? '38px' : ''}" : undefined) + +ResourceGroup(resourceGroup, getButtonClass, multipage) + + if multipage + +Paginate(api.resourceGroups, index) + +mixin Multipage() + //- Multi-page support through Knockout.js + script(src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min.js") + script + :coffee + class App + constructor: -> + @page = ko.observable 'home' + + window.app = new App() + + window.onhashchange = -> + vars = {} + for v in location.hash.substr(1).split(',') + parts = v.split ':' + vars[parts[0]] = parts[1] + + # Set the page + window.app.page vars.page or 'home' + + # Scroll to a header if Set + if vars.header + $("##{vars.header}")[0].scrollIntoView true + else + window.scrollTo 0, 0 + + ko.applyBindings window.app + + # Load the correct page + window.onhashchange() diff --git a/doc/api_documentation_layouts/openproject-layout.jade b/doc/api_documentation_layouts/openproject-layout.jade new file mode 100644 index 000000000000..39822b934a75 --- /dev/null +++ b/doc/api_documentation_layouts/openproject-layout.jade @@ -0,0 +1,190 @@ +doctype + +include openproject-includes.jade + +html + head + meta(charset="utf-8") + title= api.name || 'API Documentation' + block bootstrap-theme + link(rel="stylesheet", href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css") + link(rel="stylesheet", href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css") + block styles + link(rel="stylesheet", href="//fonts.googleapis.com/css?family=Roboto:400,700|Inconsolata|Raleway:200") + style. + /* Highlight.js Theme Tomorrow */ + .hljs-comment,.hljs-title{color:#8e908c}.hljs-variable,.hljs-attribute,.hljs-tag,.hljs-regexp,.ruby .hljs-constant,.xml .hljs-tag .hljs-title,.xml .hljs-pi,.xml .hljs-doctype,.html .hljs-doctype,.css .hljs-id,.css .hljs-class,.css .hljs-pseudo{color:#c82829}.hljs-number,.hljs-preprocessor,.hljs-pragma,.hljs-built_in,.hljs-literal,.hljs-params,.hljs-constant{color:#f5871f}.ruby .hljs-class .hljs-title,.css .hljs-rules .hljs-attribute{color:#eab700}.hljs-string,.hljs-value,.hljs-inheritance,.hljs-header,.ruby .hljs-symbol,.xml .hljs-cdata{color:#718c00}.css .hljs-hexcolor{color:#3e999f}.hljs-function,.python .hljs-decorator,.python .hljs-title,.ruby .hljs-function .hljs-title,.ruby .hljs-title .hljs-keyword,.perl .hljs-sub,.javascript .hljs-title,.coffeescript .hljs-title{color:#4271ae}.hljs-keyword,.javascript .hljs-function{color:#8959a8}.hljs{display:block;background:white;color:#4d4d4c;padding:.5em}.coffeescript .javascript,.javascript .xml,.tex .hljs-formula,.xml .javascript,.xml .vbscript,.xml .css,.xml .hljs-cdata{opacity:.5} + //style + // :stylus + // body, h4, h5 + // font-family 'Roboto' sans-serif !important + // + // h1, h2, h3, .aglio + // font-family 'Raleway' sans-serif !important + // + // h1, h2, h3, h4, h5 + // & a + // display none + // + // &:hover a + // display inline + // + // code + // color #444 + // background-color #ddd + // font-family 'Inconsolata' monospace !important + // + // a[data-target] + // cursor pointer + // + // h4 + // font-size 100% + // font-weight bold + // text-transform uppercase + // + // .back-to-top + // position fixed + // z-index 1 + // bottom 0px + // right 24px + // padding 4px 8px + // background-color #eee + // text-decoration none !important + // border-top 1px solid rgba(0, 0, 0, 0.1) + // border-left 1px solid rgba(0, 0, 0, 0.1) + // border-right 1px solid rgba(0, 0, 0, 0.1) + // border-top-left-radius 3px + // border-top-right-radius 3px + // + // .panel + // overflow hidden + // + // .panel-heading + // code + // margin-left 3px + // color #c7254e + // background-color rgba(255,255,255,0.7) + // white-space pre-wrap + // white-space -moz-pre-wrap + // white-space -pre-wrap + // white-space -o-pre-wrap + // word-wrap break-word + // h3 + // margin-top 10px + // margin-bottom 10px + // + // a.list-group-item:hover + // background-color #F8F8F8 + // border-left 2px solid #555 + // padding-left 15px + // + // .indent + // display block + // text-indent 16px + // + // .list-group-item + // padding-left 16px + // .toggle + // .open + // display block + // .closed + // display none + // + // .list-group-item.collapsed + // .toggle + // .open + // display none + // .closed + // display block + // + // a.list-group-item + // font-size 13px + // white-space nowrap + // text-overflow ellipsis + // overflow hidden + // + // &.heading + // font-size 15px + // background-color #f5f5f5 + // + // &:hover + // background-color #F8F8F8 + // + // .list-group-item.collapse + // display none + // + // .list-group-item.collapse.in + // display block + // + // .list-group-item + // a + // span.closed + // display none + // span.open + // display block + // + // .list-group-item + // a.collapsed + // span.closed + // display block + // span.open + // display none + // + // #nav + // width: inherit + // margin-top 38px + // max-width 255px + // top 0 + // bottom 0 + // padding-right 12px + // padding-bottom 12px + // overflow-y auto + // + // @media(max-width: 1199px) + // #nav + // max-width 212px + + body + //a.text-muted.back-to-top(href='#top') + // i.fa.fa-toggle-up + // |  Back to top + div(class=fullWidth ? 'container-fluid' : 'container') + .row + block nav + +Nav(false) + + .col-md-8 + div(id="op-api-content") + block content + +Content('primary', false) + + //p.text-muted(style="text-align: center;") + // | Generated by  + // a.aglio(href="https://github.com/danielgtaylor/aglio") aglio + // |  on #{date().format('DD MMM YYYY')} + // + //#localFile(style="display: none; position: absolute; top: 0; left: 0; width: 100%; color: white; background: red; font-size: 150%; text-align: center; padding: 1em;"). + // This page may not display correctly when opened as a local file. Instead, view it from a web server. + + + //script(src="//code.jquery.com/jquery-1.11.0.min.js") + //script(src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js") + //if livePreview + // script(src="/socket.io/socket.io.js") + //script + // :coffee + // # Show a warning when viewed as a local file, which will break the + // # links above that start with `//`. + // if location.protocol is 'file:' + // document.getElementById('localFile').style.display = 'block'; + //block scripts + // script + // :coffee + // $('table').addClass 'table' + // + // if livePreview + // script + // :coffee + // socket = io() + // socket.on "refresh", (msg) -> + // $(document.body).html(msg) From d05a462ab76deacc0976e6a63c8fd2c1554642a3 Mon Sep 17 00:00:00 2001 From: Andrei Date: Thu, 26 Feb 2015 15:05:27 +0200 Subject: [PATCH 2/2] removed comments https://community.openproject.org/work_packages/18727 --- .../openproject-layout.jade | 164 +----------------- 1 file changed, 1 insertion(+), 163 deletions(-) diff --git a/doc/api_documentation_layouts/openproject-layout.jade b/doc/api_documentation_layouts/openproject-layout.jade index 39822b934a75..d32589edea2d 100644 --- a/doc/api_documentation_layouts/openproject-layout.jade +++ b/doc/api_documentation_layouts/openproject-layout.jade @@ -14,140 +14,9 @@ html style. /* Highlight.js Theme Tomorrow */ .hljs-comment,.hljs-title{color:#8e908c}.hljs-variable,.hljs-attribute,.hljs-tag,.hljs-regexp,.ruby .hljs-constant,.xml .hljs-tag .hljs-title,.xml .hljs-pi,.xml .hljs-doctype,.html .hljs-doctype,.css .hljs-id,.css .hljs-class,.css .hljs-pseudo{color:#c82829}.hljs-number,.hljs-preprocessor,.hljs-pragma,.hljs-built_in,.hljs-literal,.hljs-params,.hljs-constant{color:#f5871f}.ruby .hljs-class .hljs-title,.css .hljs-rules .hljs-attribute{color:#eab700}.hljs-string,.hljs-value,.hljs-inheritance,.hljs-header,.ruby .hljs-symbol,.xml .hljs-cdata{color:#718c00}.css .hljs-hexcolor{color:#3e999f}.hljs-function,.python .hljs-decorator,.python .hljs-title,.ruby .hljs-function .hljs-title,.ruby .hljs-title .hljs-keyword,.perl .hljs-sub,.javascript .hljs-title,.coffeescript .hljs-title{color:#4271ae}.hljs-keyword,.javascript .hljs-function{color:#8959a8}.hljs{display:block;background:white;color:#4d4d4c;padding:.5em}.coffeescript .javascript,.javascript .xml,.tex .hljs-formula,.xml .javascript,.xml .vbscript,.xml .css,.xml .hljs-cdata{opacity:.5} - //style - // :stylus - // body, h4, h5 - // font-family 'Roboto' sans-serif !important - // - // h1, h2, h3, .aglio - // font-family 'Raleway' sans-serif !important - // - // h1, h2, h3, h4, h5 - // & a - // display none - // - // &:hover a - // display inline - // - // code - // color #444 - // background-color #ddd - // font-family 'Inconsolata' monospace !important - // - // a[data-target] - // cursor pointer - // - // h4 - // font-size 100% - // font-weight bold - // text-transform uppercase - // - // .back-to-top - // position fixed - // z-index 1 - // bottom 0px - // right 24px - // padding 4px 8px - // background-color #eee - // text-decoration none !important - // border-top 1px solid rgba(0, 0, 0, 0.1) - // border-left 1px solid rgba(0, 0, 0, 0.1) - // border-right 1px solid rgba(0, 0, 0, 0.1) - // border-top-left-radius 3px - // border-top-right-radius 3px - // - // .panel - // overflow hidden - // - // .panel-heading - // code - // margin-left 3px - // color #c7254e - // background-color rgba(255,255,255,0.7) - // white-space pre-wrap - // white-space -moz-pre-wrap - // white-space -pre-wrap - // white-space -o-pre-wrap - // word-wrap break-word - // h3 - // margin-top 10px - // margin-bottom 10px - // - // a.list-group-item:hover - // background-color #F8F8F8 - // border-left 2px solid #555 - // padding-left 15px - // - // .indent - // display block - // text-indent 16px - // - // .list-group-item - // padding-left 16px - // .toggle - // .open - // display block - // .closed - // display none - // - // .list-group-item.collapsed - // .toggle - // .open - // display none - // .closed - // display block - // - // a.list-group-item - // font-size 13px - // white-space nowrap - // text-overflow ellipsis - // overflow hidden - // - // &.heading - // font-size 15px - // background-color #f5f5f5 - // - // &:hover - // background-color #F8F8F8 - // - // .list-group-item.collapse - // display none - // - // .list-group-item.collapse.in - // display block - // - // .list-group-item - // a - // span.closed - // display none - // span.open - // display block - // - // .list-group-item - // a.collapsed - // span.closed - // display block - // span.open - // display none - // - // #nav - // width: inherit - // margin-top 38px - // max-width 255px - // top 0 - // bottom 0 - // padding-right 12px - // padding-bottom 12px - // overflow-y auto - // - // @media(max-width: 1199px) - // #nav - // max-width 212px + body - //a.text-muted.back-to-top(href='#top') - // i.fa.fa-toggle-up - // |  Back to top div(class=fullWidth ? 'container-fluid' : 'container') .row block nav @@ -157,34 +26,3 @@ html div(id="op-api-content") block content +Content('primary', false) - - //p.text-muted(style="text-align: center;") - // | Generated by  - // a.aglio(href="https://github.com/danielgtaylor/aglio") aglio - // |  on #{date().format('DD MMM YYYY')} - // - //#localFile(style="display: none; position: absolute; top: 0; left: 0; width: 100%; color: white; background: red; font-size: 150%; text-align: center; padding: 1em;"). - // This page may not display correctly when opened as a local file. Instead, view it from a web server. - - - //script(src="//code.jquery.com/jquery-1.11.0.min.js") - //script(src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js") - //if livePreview - // script(src="/socket.io/socket.io.js") - //script - // :coffee - // # Show a warning when viewed as a local file, which will break the - // # links above that start with `//`. - // if location.protocol is 'file:' - // document.getElementById('localFile').style.display = 'block'; - //block scripts - // script - // :coffee - // $('table').addClass 'table' - // - // if livePreview - // script - // :coffee - // socket = io() - // socket.on "refresh", (msg) -> - // $(document.body).html(msg)