Automatic generation of technical documentation

dmgtlqavf9vvl30g8hbtnyirxjo







Continuing the topic of using Asciidoc (and other similar formats) to organize continuous documentation processes, I want to consider the topic of automatic generation of technical documentation.







Automatic documentation generation is a common but very vague term. I understand by this term extraction for presentation in a convenient form of information contained in the source code and settings of the documented program (information system).







General scheme of automatic documentation generation



, ,  —  . .







  • . , . , - , , , , .  —  , JSON/YAML XML;
  • ( Asciidoc, DITA, Docbook, Markdown, reStructuredText).


, (html, docx, odt, pdf ..) ( ) . , ? , . .







:







g mxjdbl4ya0quccx1iizd2ecai







, -. Asciidoc, (reStructuredText, Markdown), ( kroki, ).









. .









, , ( Javadoc, ReST ..) .







, , , . . . , . .







.









(, , ..), .







.  — . , Junit xml report. , , ,  — Allure Framework.







, JSON-, Cucumber, , .







, , —  . , .









(, xsd-, OpenAPI, DSL , ).







, , ( Β«flattenΒ»).







( ) , .







 — 



, .







, . , , , , . .







create table geo.Strana (
    id int
    , naimenovaniye varchar(255)
    , primary key (id)
);
create table geo.Gorod (
    id int
    , naimenovaniye varchar(255)
    , strana_id int
    , constraint strana_gorod foreign key (strana_id)
        references geo.Strana(id)
);
      
      





( PostgreSQL): JSON- .







drop table if exists fk;
select x.table_schema as table_schema
    , x.table_name
    , y.table_schema as foreign_table_schema
    , y.table_name as foreign_table_name
into temp fk
from information_schema.referential_constraints rc
join information_schema.key_column_usage x
    on x.constraint_name = rc.constraint_name
join information_schema.key_column_usage y
    on y.ordinal_position = x.position_in_unique_constraint
    and y.constraint_name = rc.unique_constraint_name;
      
      





select
    json_agg(json_build_object(
        'name', t.table_schema || '.' || t.table_name
        , 'columns'
        , (select
            json_agg(json_build_object (
                'name', column_name
                ,'type', data_type
            ))
            from information_schema.columns as c
            where c.table_name = t.table_name and c.table_schema = t.table_schema
          )
        , 'fk'
        , (select
            json_agg(json_build_object (
                'fk_table'
                , fk.foreign_table_schema || '.' || fk.foreign_table_name
            ))
           from fk
           where fk.table_name = t.table_name and fk.table_schema = t.table_schema
          )
    ))
from information_schema.tables as t
where table_schema = 'geo';
      
      





JSON-:







[{
        "name": "geo.Strana",
        "columns": [{
                "name": "id",
                "type": "integer"
            }, {
                "name": "naimenovaniye",
                "type": "character varying"
            }
        ],
        "fk": null
    }, {
        "name": "geo.Gorod",
        "columns": [{
                "name": "id",
                "type": "integer"
            }, {
                "name": "naimenovaniye",
                "type": "character varying"
            }, {
                "name": "strana_id",
                "type": "integer"
            }
        ],
        "fk": [{
                "fk_table": "geo.Strana"
            }
        ]
    }
]
      
      





, .









,

. , .







, , .







( ) XSLT.  — Mustache.







. , Excel ods .







, , 2003 XSLT , , Ruby. 18 , , XSLT , .







Liquid JSON XSLT XML. Ruby, (1) Asciidoc — Asciidoctor —  Ruby (2) Ruby- java javascript, .







JSON-



JSON-.







PlantUML:







{% assign bl = "\n" %}
{%- for table in data -%}
    class {{ table.name }}{{ bl }}
    {%- for fk in table.fk -%}
        {{ table.name }} "*" -- "1" {{ fk.fk_table }}{{ bl }}
    {%- endfor -%}
{%- endfor -%}
      
      





, . PlantUML class [ ]



. .







:







class geo.Strana
class geo.Gorod
geo.Gorod "*" -- "1" geo.Strana
      
      





Asciidoc:







{% assign bl = "\n" %}{% assign bbl = "\n\n" %}
{%- for table in data -%}
    [[{{ table.name }}]]{{- bl -}}
    . {{ table.name }}{{- bl -}}
    [cols="1,3,3", options="header"]{{- bl -}}
    |==={{- bl -}}
    |β„– |  | {{ bl }}
    {%- for column in table.columns -%}
        |{counter:{{ table.name }}} |{{ column.name }} |{{ column.type }}{{- bl -}}
    {%- endfor -%}
    {%- if table.fk -%}
        3+a|     :{{- bbl -}}
        {%- for fk in table.fk -%}
            * <<{{fk.fk_table}}, {{fk.fk_table}}>>{{- bl -}}
        {%- endfor -%}
    {%- endif -%}
    |==={{- bbl -}}
{%- endfor -%}
      
      





include:







=  
:lang: ru
:figure-caption: 
:xrefstyle: short
:sectnums:

==  

      (<<struktura>>).

[[struktura]]
. 
[plantuml, struktura, png, fitrect="170x240mm", srcdpi=300, width="50%"]
....
skinparam dpi 300
left to right direction
include::pu_sql.pu[]
....

==  

include::adoc_sql.adoc[]
      
      





Asciidoc Asciidoc . Asciidoc . , . - ( , , ..).







Microsoft Word , .







ehijqkjfk8e64ogx3zo5aomx63u







,



XML-.







. , .







( xsd ) 3 — https://smev3.gosuslugi.ru/portal/inquirytype_one.jsp?id=41108&zone=fed. :







<ns1: =" 5087746429843"
    ="  5087746429843">
  <ns1: ="5087746429843" ="2008-11-18"/>
</ns1:>
<ns1:>
  <ns1: ="77" ="770000000002990" ="7"
      ="6">
    <fnst: ="" =""/>
    <fnst: ="" =" 2-"/>
    <fnst: ="5087746429843" ="2008-11-18"/>
  </ns1:>
</ns1:>
      
      





, , xsd.







Asciidoc :







<stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform"
            xmlns:ep="uri:asciidoc:doc:automation"
            extension-element-prefixes="ep">
    <output method="text" /><strip-space elements="*"/>
    <template match="/"><apply-templates/></template>
    <template match="*[count(@*|*) > 0 and count(ancestor::*) > 0]">
        <value-of select="'\n='"/>
        <for-each select="ancestor::*"><value-of select="'='"/></for-each>
        <value-of select="' '"/>
        <value-of select="concat('{',local-name(),'}')"/><text>\n\n</text>
        <text>|===\n</text>
        <for-each select="(@*)|(*[./text()])">
            <text>|</text><value-of select="concat('{',local-name(),'}')"/>
            <text>|</text><value-of select="ep:iformat(current())"/>
            <text>\n</text>
        </for-each>
        <text>|===\n</text>
        <apply-templates/>
    </template>
    <template match="text()"/>
</stylesheet>
      
      





. , .  —  . , Asciidoc |



.







XML-  —  Asciidoc. xsd- :







<?xml version="1.0" encoding="UTF-8"?>
<stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform"
            xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <output method="text" />
    <strip-space elements="*"/>
    <template match="*[@name]">
        <value-of select="concat(':', @name, ': ')"/>
        <value-of select="normalize-space(xs:annotation/xs:documentation)"/>
        <text>\n</text>
        <apply-templates/>
    </template>
    <template match="*[not(@name)]">
        <apply-templates/>
    </template>
    <template match="text()"></template>
</stylesheet>
      
      





Asciidoc ( , .. xsd) :







:sectnums:

include::adoc_egrul_xsd.adoc[]
include::adoc_egrul_xsd2.adoc[]

include::adoc_egrul.adoc[]
      
      





Microsoft Word :







mjh 6 n36odw71vbmj itjbnis0









, : , , .







, . , Asciidoc . , . . . XML JSON , . , , .







, , , , , .







, ,  —  , , . <strip-space elements="*"/>



<text>\n</text>



. \n



. , - .







Liquid , bl



.









, .







. , XSLT apply-templates



. (template



) .









Asciidoc Asciidoc. , Open API Β«;



Β». . Β«;;



Β» Asciidoc , , , .







, , .  —  iformat



. (zero space) DD.MM.YYYY.







AsciidocDocAutomation = Class.new do
  def iformat(node)
    value = node.to_s
    re = /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/
    vm = value.match(re)
    value = "#{vm[3]}.#{vm[2]}.#{vm[1]}" if !!(value =~ re)
    "&#8203;#&#8203;"
  end
end
      
      





To completely disable Asciidoc syntax in inserted values, simply escaping them.







conclusions



  • Technologies for automatic generation of documentation have been developed and they can be effectively used in IT projects of any complexity.
  • The Asciidoc markup language is technologically advanced for use in tasks of automatic generation of documentation.


And an announcement: the next article will be devoted to the issues of quality assurance of documentation in the Asciidoc format.








All Articles