diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
new file mode 100644
index 0000000000..46691c55ef
--- /dev/null
+++ b/.github/workflows/docs.yml
@@ -0,0 +1,48 @@
+name: Generate Documentation
+
+on:
+ release:
+ types: [published]
+
+jobs:
+ generate-docs:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout release code
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Set up PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: '8.2'
+ extensions: dom, curl, libxml, mbstring, zip
+
+ - name: Download Doctum
+ run: |
+ wget -q https://doctum.long-term.support/releases/latest/doctum.phar
+ chmod +x doctum.phar
+
+ - name: Switch to api-docs branch
+ run: |
+ git checkout api-docs || git checkout -b api-docs
+ git reset --hard ${{ github.sha }}
+
+ - name: Generate documentation
+ run: |
+ ./doctum.phar update doctum.php -v
+
+ - name: Commit and push documentation
+ run: |
+ git config --local user.email "docs@fieldmanager.org"
+ git config --local user.name "Fieldmanager Docs"
+ git add docs/
+ if git diff --staged --quiet; then
+ echo "No documentation changes to commit"
+ else
+ git commit -m "Update API documentation for ${{ github.event.release.tag_name }}"
+ git push origin api-docs
+ fi
diff --git a/.gitignore b/.gitignore
index 1d0f03fad7..b87083402e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,12 +25,11 @@ Thumbs.db
*.code-workspace
.idea
.vscode
-
-# Created by Apigen for logs
-build/
+.claude
# Built docs
-docs/
+cache/
+doctum.phar
# Code coverage report
report/
diff --git a/README.md b/README.md
index 3e2ec6eaa6..66946511ff 100644
--- a/README.md
+++ b/README.md
@@ -23,8 +23,10 @@ Development of Fieldmanager happens on [GitHub](http://github.com/alleyinteracti
## Generating Documentation
-To build Fieldmanager's API documentation, the latest version of which is available at [api.fieldmanager.org](https://api.fieldmanager.org), you need [apigen](https://github.com/ApiGen/ApiGen) installed. Once you've got that, you can generate the entire documentation tree as follows:
+[Fieldmanager's API documentation](https://api.fieldmanager.org) is built using [Doctum](https://github.com/code-lts/doctum) and a GitHub Action. Docs are stored in the `api-docs` branch.
+
+To build the docs manually, see the Doctum README for instructions on downloading the phar file, then you can generate the entire documentation tree by checking out the `api-docs` branch and running:
```bash
-apigen -c apigen.neon
+doctum.phar update doctum.php
```
diff --git a/apigen.neon b/apigen.neon
deleted file mode 100644
index 0e43a2c508..0000000000
--- a/apigen.neon
+++ /dev/null
@@ -1,19 +0,0 @@
-googleAnalytics: UA-17061659-8
-templateConfig: './docs-src/templates/bootstrap/config.neon'
-source: [
- php/, php/datasource/, fieldmanager.php
-]
-destination: docs/
-title: Fieldmanager
-php: no
-debug: yes
-todo: yes
-allowedHtml: [
- b,i,a,ul,ol,li,p,br,var,samp,kbd,tt,em,strong
-]
-autocomplete: [
- classes,constants,functions,methods,properties
-]
-accessLevels: [
- public
-]
diff --git a/docs-src/templates/bootstrap/404.latte b/docs-src/templates/bootstrap/404.latte
deleted file mode 100644
index 9b838179ee..0000000000
--- a/docs-src/templates/bootstrap/404.latte
+++ /dev/null
@@ -1,23 +0,0 @@
-{*
-ApiGen 2.8.0 - API documentation generator for PHP 5.3+
-
-Copyright (c) 2010-2011 David Grudl (http://davidgrudl.com)
-Copyright (c) 2011-2012 Jaroslav Hanslík (https://github.com/kukulich)
-Copyright (c) 2011-2012 Ondřej Nešpor (https://github.com/Andrewsville)
-
-For the full copyright and license information, please view
-the file LICENSE.md that was distributed with this source code.
-*}
-{layout '@layout.latte'}
-{var $robots = false}
-
-{block #title}Page not found{/block}
-
-{block #content}
-
-
{include #title}
-
The requested page could not be found.
-
You have probably clicked on a link that is outdated and points to a page that does not exist any more or you have made an typing error in the address.
-
To continue please try to find requested page in the menu,{if $config->tree} take a look at the tree view of the whole project{/if} or use search field on the top.
-
-{/block}
\ No newline at end of file
diff --git a/docs-src/templates/bootstrap/@elementlist.latte b/docs-src/templates/bootstrap/@elementlist.latte
deleted file mode 100644
index 18a70f8bbd..0000000000
--- a/docs-src/templates/bootstrap/@elementlist.latte
+++ /dev/null
@@ -1,59 +0,0 @@
-{*
-ApiGen 2.8.0 - API documentation generator for PHP 5.3+
-
-Copyright (c) 2010-2011 David Grudl (http://davidgrudl.com)
-Copyright (c) 2011-2012 Jaroslav Hanslík (https://github.com/kukulich)
-Copyright (c) 2011-2012 Ondřej Nešpor (https://github.com/Andrewsville)
-Copyright (c) 2012 Olivier Laviale (https://github.com/olvlvl)
-
-For the full copyright and license information, please view
-the file LICENSE.md that was distributed with this source code.
-*}
-{define #elements}
-
-
{if $class->interface}Interface{elseif $class->trait}Trait{else}Class{/if} {$class->shortName}
-
- {if $class->valid}
-
-
- {!$class|longDescription}
-
-
-
- -
-
- {if $item->documented}
- {last}{/last}{$item->name}{last}{/last}
- {else}{$item->name}{/if}
- {var $itemOwnInterfaces = $item->ownInterfaces}
- {if $itemOwnInterfaces} implements {foreach $itemOwnInterfaces as $interface}
- {$interface->name}{sep}, {/sep}
- {/foreach}{/if}
- {var $itemOwnTraits = $item->ownTraits}
- {if $itemOwnTraits} uses {foreach $itemOwnTraits as $trait}
- {$trait->name}{sep}, {/sep}
- {/foreach}{/if}
-
-
-
- {define #children}
-
- {foreach $children as $child}
- {$child->name}{sep}, {/sep}
- {/foreach}
-
- {/define}
-
-
-
Direct known subclasses
- {include #children, children => $directSubClasses}
-
-
-
-
Indirect known subclasses
- {include #children, children => $indirectSubClasses}
-
-
-
-
Direct known implementers
- {include #children, children => $directImplementers}
-
-
-
-
Indirect known implementers
- {include #children, children => $indirectImplementers}
-
-
-
-
Direct Known Users
- {include #children, children => $directUsers}
-
-
-
-
Indirect Known Users
- {include #children, children => $indirectUsers}
-
-
-
- {if !$class->interface && !$class->trait && ($class->abstract || $class->final)}
{if $class->abstract}Abstract{else}Final{/if}{/if}
- {if $class->internal}
PHP Extension: {$class->extension->name|firstUpper}{/if}
- {if $class->inNamespace()}
Namespace: {!$class->namespaceName|namespaceLinks}
{/if}
- {if $class->inPackage()}
Package: {!$class->packageName|packageLinks}
{/if}
-
- {foreach $template->annotationSort($template->annotationFilter($class->annotations)) as $annotation => $values}
- {foreach $values as $value}
-
{$annotation|annotationBeautify}{if $value}:{/if}
- {!$value|annotation:$annotation:$class}
- {/foreach}
- {/foreach}
- {if $class->internal}
Documented at php.net{else}
Located at {$class->fileName|relativePath}{/if}
-
-
- {var $ownMethods = $class->ownMethods}
- {var $inheritedMethods = $class->inheritedMethods}
- {var $usedMethods = $class->usedMethods}
- {var $ownMagicMethods = $class->ownMagicMethods}
- {var $inheritedMagicMethods = $class->inheritedMagicMethods}
- {var $usedMagicMethods = $class->usedMagicMethods}
-
- {if $ownMethods || $inheritedMethods || $usedMethods || $ownMagicMethods || $usedMagicMethods}
- {define #method}
-
- {var $annotations = $method->annotations}
-
-
- {if !$class->interface && $method->abstract}abstract{elseif $method->final}final{/if} {if $method->protected}protected{elseif $method->private}private{else}public{/if} {if $method->static}static{/if}
- {ifset $annotations['return']}{!$annotations['return'][0]|typeLinks:$method}{/ifset}
- {if $method->returnsReference()}&{/if}
-
- |
-
-
- #
- {block|strip}
- {if $class->internal}
- {$method->name}(
- {else}
- {$method->name}(
- {/if}
- {foreach $method->parameters as $parameter}
- {!$parameter->typeHint|typeLinks:$method}
- {if $parameter->passedByReference}& {/if}${$parameter->name}{if $parameter->defaultValueAvailable} = {!$parameter->defaultValueDefinition|highlightPHP:$class}{elseif $parameter->unlimited},…{/if}{sep}, {/sep}
- {/foreach}
- ){/block}
-
- {if $config->template['options']['elementDetailsCollapsed']}
-
- {!$method|shortDescription:true}
-
- {/if}
-
-
- {!$method|longDescription}
-
- {if !$class->deprecated && $method->deprecated}
- Deprecated
- {ifset $annotations['deprecated']}
-
- {foreach $annotations['deprecated'] as $description}
- {if $description}
- {!$description|annotation:'deprecated':$method}
- {/if}
- {/foreach}
-
- {/ifset}
- {/if}
-
- {if $method->parameters && isset($annotations['param'])}
- Parameters
-
- {foreach $method->parameters as $parameter}
- - ${$parameter->name}{if $parameter->unlimited},…{/if}
- - {ifset $annotations['param'][$parameter->position]}{!$annotations['param'][$parameter->position]|annotation:'param':$method}{/ifset}
- {/foreach}
-
- {/if}
-
- {if isset($annotations['return']) && 'void' !== $annotations['return'][0]}
- Returns
-
- {foreach $annotations['return'] as $description}
- {!$description|annotation:'return':$method}
- {/foreach}
-
- {/if}
-
- {ifset $annotations['throws']}
- Throws
-
- {foreach $annotations['throws'] as $description}
- {!$description|annotation:'throws':$method}
- {/foreach}
-
- {/ifset}
-
- {foreach $template->annotationSort($template->annotationFilter($annotations, array('deprecated', 'param', 'return', 'throws'))) as $annotation => $descriptions}
- {$annotation|annotationBeautify}
-
- {foreach $descriptions as $description}
- {if $description}
- {!$description|annotation:$annotation:$method}
- {/if}
- {/foreach}
-
- {/foreach}
-
- {var $overriddenMethod = $method->overriddenMethod}
- {if $overriddenMethod}
- Overrides
-
- {/if}
-
- {var $implementedMethod = $method->implementedMethod}
- {if $implementedMethod}
- Implementation of
-
- {/if}
-
- |
-
- {/define}
-
-
Methods summary
-
- {foreach $ownMethods as $method}
- {include #method, method => $method}
- {/foreach}
-
-
- {foreach $inheritedMethods as $parentName => $methods}
-
-
- {foreach $methods as $method}
- {$method->name}(){sep}, {/sep}
- {/foreach}
-
- {/foreach}
-
- {foreach $usedMethods as $traitName => $methods}
-
-
- {foreach $methods as $data}
- {$data['method']->name}(){if $data['aliases']}(as {foreach $data['aliases'] as $alias}{$alias->name}(){sep}, {/sep}{/foreach}){/if}{sep}, {/sep}
- {/foreach}
-
- {/foreach}
-
-
Magic methods summary
-
- {foreach $ownMagicMethods as $method}
- {include #method, method => $method}
- {/foreach}
-
-
- {foreach $inheritedMagicMethods as $parentName => $methods}
-
Magic methods inherited from {$parentName}
-
- {foreach $methods as $method}
- {$method->name}(){sep}, {/sep}
- {/foreach}
-
- {/foreach}
-
- {foreach $usedMagicMethods as $traitName => $methods}
-
-
- {foreach $methods as $data}
- {$data['method']->name}(){if $data['aliases']}(as {foreach $data['aliases'] as $alias}{$alias->name}(){sep}, {/sep}{/foreach}){/if}{sep}, {/sep}
- {/foreach}
-
- {/foreach}
- {/if}
-
-
- {var $ownConstants = $class->ownConstants}
- {var $inheritedConstants = $class->inheritedConstants}
-
- {if $ownConstants || $inheritedConstants}
-
Constants summary
-
-
- {var $annotations = $constant->annotations}
-
- {!$constant->typeHint|typeLinks:$constant} |
-
- {if $class->internal}
- {$constant->name}
- {else}
- {$constant->name}
- {/if}
- |
- {!$constant->valueDefinition|highlightValue:$class} |
-
- #
-
- {if $config->template['options']['elementDetailsCollapsed']}
-
- {!$constant|shortDescription:true}
-
- {/if}
-
-
- {!$constant|longDescription}
-
- {foreach $template->annotationSort($template->annotationFilter($annotations, array('var'))) as $annotation => $descriptions}
- {$annotation|annotationBeautify}
-
- {foreach $descriptions as $description}
- {if $description}
- {!$description|annotation:$annotation:$constant}
- {/if}
- {/foreach}
-
- {/foreach}
-
- |
-
-
-
- {foreach $inheritedConstants as $parentName => $constants}
-
-
- {foreach $constants as $constant}
- {$constant->name}{sep}, {/sep}
- {/foreach}
-
- {/foreach}
- {/if}
-
- {var $ownProperties = $class->ownProperties}
- {var $inheritedProperties = $class->inheritedProperties}
- {var $usedProperties = $class->usedProperties}
- {var $ownMagicProperties = $class->ownMagicProperties}
- {var $inheritedMagicProperties = $class->inheritedMagicProperties}
- {var $usedMagicProperties = $class->usedMagicProperties}
-
- {if $ownProperties || $inheritedProperties || $usedProperties || $ownMagicProperties || $inheritedMagicProperties || $usedMagicProperties}
- {define #property}
-
-
- {if $property->protected}protected{elseif $property->private}private{else}public{/if} {if $property->static}static{/if} {if $property->readOnly}read-only{elseif $property->writeOnly}write-only{/if}
- {!$property->typeHint|typeLinks:$property}
- |
-
-
- {if $class->internal}
- ${$property->name}
- {else}
- ${$property->name}
- {/if}
- |
- {!$property->defaultValueDefinition|highlightValue:$class} |
-
- #
-
- {if $config->template['options']['elementDetailsCollapsed']}
-
- {!$property|shortDescription:true}
-
- {/if}
-
-
- {!$property|longDescription}
-
- {foreach $template->annotationSort($template->annotationFilter($property->annotations, array('var'))) as $annotation => $descriptions}
- {$annotation|annotationBeautify}
-
- {foreach $descriptions as $description}
- {if $description}
- {!$description|annotation:$annotation:$property}
- {/if}
- {/foreach}
-
- {/foreach}
-
- |
-
- {/define}
-
-
Properties summary
-
- {foreach $ownProperties as $property}
- {include #property, property => $property}
- {/foreach}
-
-
- {foreach $inheritedProperties as $parentName => $properties}
-
-
- {foreach $properties as $property}
- ${$property->name}{sep}, {/sep}
- {/foreach}
-
- {/foreach}
-
- {foreach $usedProperties as $traitName => $properties}
-
-
- {foreach $properties as $property}
- ${$property->name}{sep}, {/sep}
- {/foreach}
-
- {/foreach}
-
- {if $ownMagicProperties}
-
Magic properties
-
- {foreach $ownMagicProperties as $property}
- {include #property, property => $property}
- {/foreach}
-
- {/if}
-
- {foreach $inheritedMagicProperties as $parentName => $properties}
-
Magic properties inherited from {$parentName}
-
- {foreach $properties as $property}
- ${$property->name}{sep}, {/sep}
- {/foreach}
-
- {/foreach}
-
- {foreach $usedMagicProperties as $traitName => $properties}
-
Magic properties used from {$traitName}
-
- {foreach $properties as $property}
- ${$property->name}{sep}, {/sep}
- {/foreach}
-
- {/foreach}
- {/if}
-
- {else}
-
-
- Documentation of this class could not be generated.
-
-
- Class was originally declared in {$class->fileName|relativePath} and is invalid because of:
-
-
- - Class was redeclared in {$reason->getSender()->getFileName()|relativePath}.
-
-
- {/if}
-
-{/block}
diff --git a/docs-src/templates/bootstrap/combined.js.latte b/docs-src/templates/bootstrap/combined.js.latte
deleted file mode 100644
index ad9fa3fb21..0000000000
--- a/docs-src/templates/bootstrap/combined.js.latte
+++ /dev/null
@@ -1,22 +0,0 @@
-{*
-ApiGen 2.8.0 - API documentation generator for PHP 5.3+
-
-Copyright (c) 2010-2011 David Grudl (http://davidgrudl.com)
-Copyright (c) 2011-2012 Jaroslav Hanslík (https://github.com/kukulich)
-Copyright (c) 2011-2012 Ondřej Nešpor (https://github.com/Andrewsville)
-Copyright (c) 2012 Olivier Laviale (https://github.com/olvlvl)
-
-For the full copyright and license information, please view
-the file LICENSE.md that was distributed with this source code.
-*}
-{contentType javascript}
-
-var ApiGen = ApiGen || {};
-ApiGen.config = {$config->template};
-
-{var $scripts = ['jquery.min.js', 'jquery.cookie.js', 'jquery.sprintf.js', 'jquery.autocomplete.js', 'jquery.sortElements.js', 'main.js']}
-{var $dir = dirname($template->getFile())}
-
-{foreach $scripts as $script}
-{!file_get_contents("$dir/js/$script")}
-{/foreach}
diff --git a/docs-src/templates/bootstrap/config.neon b/docs-src/templates/bootstrap/config.neon
deleted file mode 100644
index 6ddc2f6951..0000000000
--- a/docs-src/templates/bootstrap/config.neon
+++ /dev/null
@@ -1,56 +0,0 @@
-require:
- min: 2.8.0
-
-resources:
- resources: resources
-
-templates:
- common:
- overview.latte: index.html
- combined.js.latte: resources/combined.js
- elementlist.js.latte: elementlist.js
- 404.latte: 404.html
-
- main:
- package:
- filename: package-%s.html
- template: package.latte
- namespace:
- filename: namespace-%s.html
- template: namespace.latte
- class:
- filename: class-%s.html
- template: class.latte
- constant:
- filename: constant-%s.html
- template: constant.latte
- function:
- filename: function-%s.html
- template: function.latte
- source:
- filename: source-%s.html
- template: source.latte
- tree:
- filename: tree.html
- template: tree.latte
- deprecated:
- filename: deprecated.html
- template: deprecated.latte
- todo:
- filename: todo.html
- template: todo.latte
-
- optional:
- sitemap:
- filename: sitemap.xml
- template: sitemap.xml.latte
- opensearch:
- filename: opensearch.xml
- template: opensearch.xml.latte
- robots:
- filename: robots.txt
- template: robots.txt.latte
-
-options:
- elementDetailsCollapsed: Yes
- elementsOrder: natural # alphabetical
diff --git a/docs-src/templates/bootstrap/constant.latte b/docs-src/templates/bootstrap/constant.latte
deleted file mode 100644
index 43ad423962..0000000000
--- a/docs-src/templates/bootstrap/constant.latte
+++ /dev/null
@@ -1,67 +0,0 @@
-{*
-ApiGen 2.8.0 - API documentation generator for PHP 5.3+
-
-Copyright (c) 2010-2011 David Grudl (http://davidgrudl.com)
-Copyright (c) 2011-2012 Jaroslav Hanslík (https://github.com/kukulich)
-Copyright (c) 2011-2012 Ondřej Nešpor (https://github.com/Andrewsville)
-Copyright (c) 2012 Olivier Laviale (https://github.com/olvlvl)
-
-For the full copyright and license information, please view
-the file LICENSE.md that was distributed with this source code.
-*}
-{layout '@layout.latte'}
-{var $active = 'constant'}
-
-{block #title}{if $constant->deprecated}Deprecated {/if}Constant {$constant->name}{/block}
-
-{block #content}
-
-
Constant {$constant->shortName}
-
- {if $constant->valid}
-
-
- {!$constant|longDescription}
-
-
-
- {if $constant->inNamespace()}
Namespace: {!$constant->namespaceName|namespaceLinks}
{/if}
- {if $constant->inPackage()}
Package: {!$constant->packageName|packageLinks}
{/if}
- {foreach $template->annotationSort($template->annotationFilter($constant->annotations, array('var'))) as $annotation => $values}
- {foreach $values as $value}
-
{$annotation|annotationBeautify}{if $value}:{/if}
- {!$value|annotation:$annotation:$constant}
- {/foreach}
- {/foreach}
-
Located at {$constant->fileName|relativePath}
-
-
- {var $annotations = $constant->annotations}
-
-
Value summary
-
-
- {!$constant->typeHint|typeLinks:$constant} |
- {block|strip}
- {var $element = $template->resolveElement($constant->valueDefinition, $constant)}
- {if $element}{$constant->valueDefinition}{else}{!$constant->valueDefinition|highlightValue:$constant}{/if}
- {/block} |
- {ifset $annotations['var']}{!$annotations['var'][0]|description:$constant}{/ifset} |
-
-
-
- {else}
-
-
- Documentation of this constant could not be generated.
-
-
- Constant was originally declared in {$constant->fileName|relativePath} and is invalid because of:
-
-
- - Constant was redeclared in {$reason->getSender()->getFileName()|relativePath}.
-
-
- {/if}
-
-{/block}
diff --git a/docs-src/templates/bootstrap/deprecated.latte b/docs-src/templates/bootstrap/deprecated.latte
deleted file mode 100644
index 427afc7c5b..0000000000
--- a/docs-src/templates/bootstrap/deprecated.latte
+++ /dev/null
@@ -1,137 +0,0 @@
-{*
-ApiGen 2.8.0 - API documentation generator for PHP 5.3+
-
-Copyright (c) 2010-2011 David Grudl (http://davidgrudl.com)
-Copyright (c) 2011-2012 Jaroslav Hanslík (https://github.com/kukulich)
-Copyright (c) 2011-2012 Ondřej Nešpor (https://github.com/Andrewsville)
-Copyright (c) 2012 Olivier Laviale (https://github.com/olvlvl)
-
-For the full copyright and license information, please view
-the file LICENSE.md that was distributed with this source code.
-*}
-{layout '@layout.latte'}
-{var $active = 'deprecated'}
-
-{block #title}Deprecated{/block}
-
-{block #content}
-
-
{include #title}
-
- {define #classes}
-
- | {$class->name} |
-
- {foreach $class->annotations['deprecated'] as $description}
- {if $description}
- {!$description|annotation:'deprecated':$class}
- {/if}
- {/foreach}
- |
-
- {/define}
-
- {if $deprecatedClasses}
-
Classes summary
-
- {include #classes, items => $deprecatedClasses}
-
- {/if}
-
- {if $deprecatedInterfaces}
-
Interfaces summary
-
- {include #classes, items => $deprecatedInterfaces}
-
- {/if}
-
- {if $deprecatedTraits}
-
Traits summary
-
- {include #classes, items => $deprecatedTraits}
-
- {/if}
-
- {if $deprecatedExceptions}
-
Exceptions summary
-
- {include #classes, items => $deprecatedExceptions}
-
- {/if}
-
- {if $deprecatedMethods}
-
Methods summary
-
-
- | {$method->declaringClassName} |
- {$method->name}() |
-
- {if $method->hasAnnotation('deprecated')}
- {foreach $method->annotations['deprecated'] as $description}
- {if $description}
- {!$description|annotation:'deprecated':$method}
- {/if}
- {/foreach}
- {/if}
- |
-
-
- {/if}
-
- {if $deprecatedConstants}
-
Constants summary
-
- {/if}
-
- {if $deprecatedProperties}
-
Properties summary
-
- {/if}
-
- {if $deprecatedFunctions}
-
Functions summary
-
- {/if}
-
-{/block}
diff --git a/docs-src/templates/bootstrap/elementlist.js.latte b/docs-src/templates/bootstrap/elementlist.js.latte
deleted file mode 100644
index 176b164dfd..0000000000
--- a/docs-src/templates/bootstrap/elementlist.js.latte
+++ /dev/null
@@ -1,15 +0,0 @@
-{*
-ApiGen 2.8.0 - API documentation generator for PHP 5.3+
-
-Copyright (c) 2010-2011 David Grudl (http://davidgrudl.com)
-Copyright (c) 2011-2012 Jaroslav Hanslík (https://github.com/kukulich)
-Copyright (c) 2011-2012 Ondřej Nešpor (https://github.com/Andrewsville)
-Copyright (c) 2012 Olivier Laviale (https://github.com/olvlvl)
-
-For the full copyright and license information, please view
-the file LICENSE.md that was distributed with this source code.
-*}
-{contentType javascript}
-
-var ApiGen = ApiGen || {};
-ApiGen.elements = {$elements};
diff --git a/docs-src/templates/bootstrap/function.latte b/docs-src/templates/bootstrap/function.latte
deleted file mode 100644
index fba90ca4eb..0000000000
--- a/docs-src/templates/bootstrap/function.latte
+++ /dev/null
@@ -1,98 +0,0 @@
-{*
-ApiGen 2.8.0 - API documentation generator for PHP 5.3+
-
-Copyright (c) 2010-2011 David Grudl (http://davidgrudl.com)
-Copyright (c) 2011-2012 Jaroslav Hanslík (https://github.com/kukulich)
-Copyright (c) 2011-2012 Ondřej Nešpor (https://github.com/Andrewsville)
-Copyright (c) 2012 Olivier Laviale (https://github.com/olvlvl)
-
-For the full copyright and license information, please view
-the file LICENSE.md that was distributed with this source code.
-*}
-{layout '@layout.latte'}
-{var $active = 'function'}
-
-{block #title}{if $function->deprecated}Deprecated {/if}Function {$function->name}{/block}
-
-{block #content}
-
-
Function {$function->shortName}
-
- {if $function->valid}
-
-
- {!$function|longDescription}
-
-
-
- {if $function->inNamespace()}
Namespace: {!$function->namespaceName|namespaceLinks}
{/if}
- {if $function->inPackage()}
Package: {!$function->packageName|packageLinks}
{/if}
- {foreach $template->annotationSort($template->annotationFilter($function->annotations, array('param', 'return', 'throws'))) as $annotation => $values}
- {foreach $values as $value}
-
{$annotation|annotationBeautify}{if $value}:{/if}
- {!$value|annotation:$annotation:$function}
- {/foreach}
- {/foreach}
-
Located at {$function->fileName|relativePath}
-
-
- {var $annotations = $function->annotations}
-
- {if $function->numberOfParameters}
-
Parameters summary
-
-
- {!$parameter->typeHint|typeLinks:$function} |
- {block|strip}
- {if $parameter->passedByReference}& {/if}${$parameter->name}{if $parameter->defaultValueAvailable} = {!$parameter->defaultValueDefinition|highlightPHP:$function}{elseif $parameter->unlimited},…{/if}
- {/block} |
-
- {ifset $annotations['param'][$parameter->position]}{!$annotations['param'][$parameter->position]|description:$parameter}{/ifset}
- |
-
-
- {/if}
-
- {if isset($annotations['return']) && 'void' !== $annotations['return'][0]}
-
Return value summary
-
-
-
- {!$annotations['return'][0]|typeLinks:$function}
- |
-
- {!$annotations['return'][0]|description:$function}
- |
-
-
- {/if}
-
- {if isset($annotations['throws'])}
-
Thrown exceptions summary
-
-
-
- {!$throws|typeLinks:$function}
- |
-
- {!$throws|description:$function}
- |
-
-
- {/if}
-
- {else}
-
-
- Documentation of this function could not be generated.
-
-
- Function was originally declared in {$function->fileName|relativePath} and is invalid because of:
-
-
- - Function was redeclared in {$reason->getSender()->getFileName()|relativePath}.
-
-
- {/if}
-
-{/block}
diff --git a/docs-src/templates/bootstrap/js/jquery.autocomplete.js b/docs-src/templates/bootstrap/js/jquery.autocomplete.js
deleted file mode 100644
index b8bec34df5..0000000000
--- a/docs-src/templates/bootstrap/js/jquery.autocomplete.js
+++ /dev/null
@@ -1,799 +0,0 @@
-/*!
- * jQuery Autocomplete plugin 1.1
- *
- * Copyright (c) 2009 Jörn Zaefferer
- *
- * Dual licensed under the MIT and GPL licenses:
- * http://www.opensource.org/licenses/mit-license.php
- * http://www.gnu.org/licenses/gpl.html
- *
- * Revision: $Id: jquery.autocomplete.js 15 2009-08-22 10:30:27Z joern.zaefferer $
- */
-
-;(function($) {
-
-$.fn.extend({
- autocomplete: function(urlOrData, options) {
- var isUrl = typeof urlOrData == "string";
- options = $.extend({}, $.Autocompleter.defaults, {
- url: isUrl ? urlOrData : null,
- data: isUrl ? null : urlOrData,
- delay: isUrl ? $.Autocompleter.defaults.delay : 10,
- max: options && !options.scroll ? 10 : 150
- }, options);
-
- // if highlight is set to false, replace it with a do-nothing function
- options.highlight = options.highlight || function(value) { return value; };
-
- // if the formatMatch option is not specified, then use formatItem for backwards compatibility
- options.formatMatch = options.formatMatch || options.formatItem;
-
- options.show = options.show || function(list) {};
-
- return this.each(function() {
- new $.Autocompleter(this, options);
- });
- },
- result: function(handler) {
- return this.bind("result", handler);
- },
- search: function(handler) {
- return this.trigger("search", [handler]);
- },
- flushCache: function() {
- return this.trigger("flushCache");
- },
- setOptions: function(options){
- return this.trigger("setOptions", [options]);
- },
- unautocomplete: function() {
- return this.trigger("unautocomplete");
- }
-});
-
-$.Autocompleter = function(input, options) {
-
- var KEY = {
- UP: 38,
- DOWN: 40,
- DEL: 46,
- TAB: 9,
- RETURN: 13,
- ESC: 27,
- COMMA: 188,
- PAGEUP: 33,
- PAGEDOWN: 34,
- BACKSPACE: 8
- };
-
- // Create $ object for input element
- var $input = $(input).attr("autocomplete", "off").addClass(options.inputClass);
-
- var timeout;
- var previousValue = "";
- var cache = $.Autocompleter.Cache(options);
- var hasFocus = 0;
- var lastKeyPressCode;
- var config = {
- mouseDownOnSelect: false
- };
- var select = $.Autocompleter.Select(options, input, selectCurrent, config);
-
- // only opera doesn't trigger keydown multiple times while pressed, others don't work with keypress at all
- $input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) {
- // a keypress means the input has focus
- // avoids issue where input had focus before the autocomplete was applied
- hasFocus = 1;
- // track last key pressed
- lastKeyPressCode = event.keyCode;
- switch(event.keyCode) {
-
- case KEY.UP:
- event.preventDefault();
- if ( select.visible() ) {
- select.prev();
- } else {
- onChange(0, true);
- }
- break;
-
- case KEY.DOWN:
- event.preventDefault();
- if ( select.visible() ) {
- select.next();
- } else {
- onChange(0, true);
- }
- break;
-
- case KEY.PAGEUP:
- event.preventDefault();
- if ( select.visible() ) {
- select.pageUp();
- } else {
- onChange(0, true);
- }
- break;
-
- case KEY.PAGEDOWN:
- event.preventDefault();
- if ( select.visible() ) {
- select.pageDown();
- } else {
- onChange(0, true);
- }
- break;
-
- // matches also semicolon
- case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA:
- case KEY.TAB:
- case KEY.RETURN:
- if( selectCurrent() ) {
- //event.preventDefault();
- //return false;
- }
- break;
-
- case KEY.ESC:
- select.hide();
- break;
-
- default:
- clearTimeout(timeout);
- timeout = setTimeout(onChange, options.delay);
- break;
- }
- }).focus(function(){
- // track whether the field has focus, we shouldn't process any
- // results if the field no longer has focus
- hasFocus++;
- }).blur(function() {
- hasFocus = 0;
- if (!config.mouseDownOnSelect) {
- hideResults();
- }
- }).click(function() {
- // show select when clicking in a focused field
- if ( hasFocus++ > 1 && !select.visible() ) {
- onChange(0, true);
- }
- }).bind("search", function() {
- // TODO why not just specifying both arguments?
- var fn = (arguments.length > 1) ? arguments[1] : null;
- function findValueCallback(q, data) {
- var result;
- if( data && data.length ) {
- for (var i=0; i < data.length; i++) {
- if( data[i].result.toLowerCase() == q.toLowerCase() ) {
- result = data[i];
- break;
- }
- }
- }
- if( typeof fn == "function" ) fn(result);
- else $input.trigger("result", result && [result.data, result.value]);
- }
- $.each(trimWords($input.val()), function(i, value) {
- request(value, findValueCallback, findValueCallback);
- });
- }).bind("flushCache", function() {
- cache.flush();
- }).bind("setOptions", function() {
- $.extend(options, arguments[1]);
- // if we've updated the data, repopulate
- if ( "data" in arguments[1] )
- cache.populate();
- }).bind("unautocomplete", function() {
- select.unbind();
- $input.unbind();
- $(input.form).unbind(".autocomplete");
- });
-
-
- function selectCurrent() {
- var selected = select.selected();
- if( !selected )
- return false;
-
- var v = selected.result;
- previousValue = v;
-
- if ( options.multiple ) {
- var words = trimWords($input.val());
- if ( words.length > 1 ) {
- var seperator = options.multipleSeparator.length;
- var cursorAt = $(input).selection().start;
- var wordAt, progress = 0;
- $.each(words, function(i, word) {
- progress += word.length;
- if (cursorAt <= progress) {
- wordAt = i;
- return false;
- }
- progress += seperator;
- });
- words[wordAt] = v;
- // TODO this should set the cursor to the right position, but it gets overriden somewhere
- //$.Autocompleter.Selection(input, progress + seperator, progress + seperator);
- v = words.join( options.multipleSeparator );
- }
- v += options.multipleSeparator;
- }
-
- $input.val(v);
- hideResultsNow();
- $input.trigger("result", [selected.data, selected.value]);
- return true;
- }
-
- function onChange(crap, skipPrevCheck) {
- if( lastKeyPressCode == KEY.DEL ) {
- select.hide();
- return;
- }
-
- var currentValue = $input.val();
-
- if ( !skipPrevCheck && currentValue == previousValue )
- return;
-
- previousValue = currentValue;
-
- currentValue = lastWord(currentValue);
- if ( currentValue.length >= options.minChars) {
- $input.addClass(options.loadingClass);
- if (!options.matchCase)
- currentValue = currentValue.toLowerCase();
- request(currentValue, receiveData, hideResultsNow);
- } else {
- stopLoading();
- select.hide();
- }
- };
-
- function trimWords(value) {
- if (!value)
- return [""];
- if (!options.multiple)
- return [$.trim(value)];
- return $.map(value.split(options.multipleSeparator), function(word) {
- return $.trim(value).length ? $.trim(word) : null;
- });
- }
-
- function lastWord(value) {
- if ( !options.multiple )
- return value;
- var words = trimWords(value);
- if (words.length == 1)
- return words[0];
- var cursorAt = $(input).selection().start;
- if (cursorAt == value.length) {
- words = trimWords(value)
- } else {
- words = trimWords(value.replace(value.substring(cursorAt), ""));
- }
- return words[words.length - 1];
- }
-
- // fills in the input box w/the first match (assumed to be the best match)
- // q: the term entered
- // sValue: the first matching result
- function autoFill(q, sValue){
- // autofill in the complete box w/the first match as long as the user hasn't entered in more data
- // if the last user key pressed was backspace, don't autofill
- if( options.autoFill && (lastWord($input.val()).toLowerCase() == q.toLowerCase()) && lastKeyPressCode != KEY.BACKSPACE ) {
- // fill in the value (keep the case the user has typed)
- $input.val($input.val() + sValue.substring(lastWord(previousValue).length));
- // select the portion of the value not typed by the user (so the next character will erase)
- $(input).selection(previousValue.length, previousValue.length + sValue.length);
- }
- };
-
- function hideResults() {
- clearTimeout(timeout);
- timeout = setTimeout(hideResultsNow, 200);
- };
-
- function hideResultsNow() {
- var wasVisible = select.visible();
- select.hide();
- clearTimeout(timeout);
- stopLoading();
- if (options.mustMatch) {
- // call search and run callback
- $input.search(
- function (result){
- // if no value found, clear the input box
- if( !result ) {
- if (options.multiple) {
- var words = trimWords($input.val()).slice(0, -1);
- $input.val( words.join(options.multipleSeparator) + (words.length ? options.multipleSeparator : "") );
- }
- else {
- $input.val( "" );
- $input.trigger("result", null);
- }
- }
- }
- );
- }
- };
-
- function receiveData(q, data) {
- if ( data && data.length && hasFocus ) {
- stopLoading();
- select.display(data, q);
- autoFill(q, data[0].value);
- select.show();
- } else {
- hideResultsNow();
- }
- };
-
- function request(term, success, failure) {
- if (!options.matchCase)
- term = term.toLowerCase();
- var data = cache.load(term);
- // recieve the cached data
- if (data && data.length) {
- success(term, data);
- // if an AJAX url has been supplied, try loading the data now
- } else if( (typeof options.url == "string") && (options.url.length > 0) ){
-
- var extraParams = {
- timestamp: +new Date()
- };
- $.each(options.extraParams, function(key, param) {
- extraParams[key] = typeof param == "function" ? param() : param;
- });
-
- $.ajax({
- // try to leverage ajaxQueue plugin to abort previous requests
- mode: "abort",
- // limit abortion to this input
- port: "autocomplete" + input.name,
- dataType: options.dataType,
- url: options.url,
- data: $.extend({
- q: lastWord(term),
- limit: options.max
- }, extraParams),
- success: function(data) {
- var parsed = options.parse && options.parse(data) || parse(data);
- cache.add(term, parsed);
- success(term, parsed);
- }
- });
- } else {
- // if we have a failure, we need to empty the list -- this prevents the the [TAB] key from selecting the last successful match
- select.emptyList();
- failure(term);
- }
- };
-
- function parse(data) {
- var parsed = [];
- var rows = data.split("\n");
- for (var i=0; i < rows.length; i++) {
- var row = $.trim(rows[i]);
- if (row) {
- row = row.split("|");
- parsed[parsed.length] = {
- data: row,
- value: row[0],
- result: options.formatResult && options.formatResult(row, row[0]) || row[0]
- };
- }
- }
- return parsed;
- };
-
- function stopLoading() {
- $input.removeClass(options.loadingClass);
- };
-
-};
-
-$.Autocompleter.defaults = {
- inputClass: "ac_input",
- resultsClass: "ac_results",
- loadingClass: "ac_loading",
- minChars: 1,
- delay: 400,
- matchCase: false,
- matchSubset: true,
- matchContains: false,
- cacheLength: 10,
- max: 100,
- mustMatch: false,
- extraParams: {},
- selectFirst: true,
- formatItem: function(row) { return row[0]; },
- formatMatch: null,
- autoFill: false,
- width: 0,
- multiple: false,
- multipleSeparator: ", ",
- highlight: function(value, term) {
- return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "