apress-documentation 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/.drone.yml +28 -0
  3. data/.gitignore +10 -0
  4. data/Appraisals +30 -0
  5. data/CHANGELOG.md +34 -0
  6. data/Gemfile +4 -0
  7. data/README.md +101 -0
  8. data/Rakefile +6 -0
  9. data/app/assets/javascripts/package/documentation.js +18 -0
  10. data/app/assets/javascripts/shared/dependency_switcher.js +10 -0
  11. data/app/assets/javascripts/swagger_binder.js +19 -0
  12. data/app/assets/javascripts/swagger_ui.js +24 -0
  13. data/app/assets/javascripts/templates/document.hamlbars +25 -0
  14. data/app/assets/stylesheets/document/base.scss +112 -0
  15. data/app/assets/stylesheets/document/document.scss +19 -0
  16. data/app/assets/stylesheets/document/layout.scss +9 -0
  17. data/app/assets/stylesheets/document/sidebar.scss +19 -0
  18. data/app/assets/stylesheets/document/swagger.scss +3 -0
  19. data/app/assets/stylesheets/document/switch.scss +46 -0
  20. data/app/assets/stylesheets/document/variables.scss +26 -0
  21. data/app/assets/stylesheets/package/documentation.css +9 -0
  22. data/app/assets/stylesheets/package/swagger_print.css +4 -0
  23. data/app/assets/stylesheets/package/swagger_screen.css +4 -0
  24. data/app/controllers/apress/documentation/documents_controller.rb +14 -0
  25. data/app/controllers/apress/documentation/swagger_controller.rb +22 -0
  26. data/app/controllers/apress/documentation/swagger_ui_controller.rb +11 -0
  27. data/app/controllers/concerns/apress/documentation/preload_docs.rb +20 -0
  28. data/app/helpers/apress/documentation/documents_helper.rb +14 -0
  29. data/app/presenters/apress/documentation/dependency_presenter.rb +75 -0
  30. data/app/services/apress/documentation/swagger_json_builder.rb +22 -0
  31. data/app/views/apress/documentation/documents/_document.html.haml +32 -0
  32. data/app/views/apress/documentation/documents/_swagger.html.haml +10 -0
  33. data/app/views/apress/documentation/documents/show.html.haml +13 -0
  34. data/app/views/apress/documentation/presenters/dependency_presenter/_dependencies.html.haml +21 -0
  35. data/app/views/apress/documentation/presenters/dependency_presenter/_links.html.haml +17 -0
  36. data/app/views/apress/documentation/swagger_ui/show.html.haml +26 -0
  37. data/app/views/layouts/apress/documentation/_menu.html.haml +6 -0
  38. data/app/views/layouts/apress/documentation/_menu_item.html.haml +7 -0
  39. data/app/views/layouts/apress/documentation/_sidebar.html.haml +2 -0
  40. data/app/views/layouts/documentation.html.haml +17 -0
  41. data/apress-documentation.gemspec +35 -0
  42. data/config/routes.rb +16 -0
  43. data/dip.yml +48 -0
  44. data/docker-compose.development.yml +18 -0
  45. data/docker-compose.drone.yml +7 -0
  46. data/docker-compose.yml +10 -0
  47. data/lib/apress/documentation.rb +48 -0
  48. data/lib/apress/documentation/dsl/compilers/base_compiler.rb +32 -0
  49. data/lib/apress/documentation/dsl/compilers/document_compiler.rb +111 -0
  50. data/lib/apress/documentation/dsl/compilers/mixins/dependable.rb +31 -0
  51. data/lib/apress/documentation/dsl/compilers/mixins/publicity.rb +34 -0
  52. data/lib/apress/documentation/dsl/compilers/swagger_compiler.rb +25 -0
  53. data/lib/apress/documentation/dsl/document.rb +14 -0
  54. data/lib/apress/documentation/dsl/modules.rb +40 -0
  55. data/lib/apress/documentation/dsl/swagger_document.rb +14 -0
  56. data/lib/apress/documentation/dsl/utils/swagger_bind_point_extractor.rb +37 -0
  57. data/lib/apress/documentation/engine.rb +16 -0
  58. data/lib/apress/documentation/extensions/rgl/adjacency.rb +18 -0
  59. data/lib/apress/documentation/storage/base_storage.rb +88 -0
  60. data/lib/apress/documentation/storage/dependency_graph.rb +96 -0
  61. data/lib/apress/documentation/storage/document.rb +52 -0
  62. data/lib/apress/documentation/storage/modules.rb +83 -0
  63. data/lib/apress/documentation/storage/swagger_document.rb +62 -0
  64. data/lib/apress/documentation/swagger/schema.rb +39 -0
  65. data/lib/apress/documentation/version.rb +5 -0
  66. data/spec/app/controllers/documents_controller_spec.rb +42 -0
  67. data/spec/app/controllers/swagger_controller_spec.rb +46 -0
  68. data/spec/app/controllers/swagger_ui_controller_spec.rb +11 -0
  69. data/spec/app/services/swagger_json_builder_spec.rb +41 -0
  70. data/spec/apress/documentation_spec.rb +342 -0
  71. data/spec/helpers/apress/documentation/documents_helper_spec.rb +17 -0
  72. data/spec/internal/app/docs/swagger/root.rb +7 -0
  73. data/spec/internal/config/database.yml +7 -0
  74. data/spec/internal/config/environments/test.rb +1 -0
  75. data/spec/internal/config/hosts.rb +1 -0
  76. data/spec/internal/config/routes.rb +3 -0
  77. data/spec/internal/lib/stub_docs/module.rb +3 -0
  78. data/spec/internal/lib/stub_docs/module/document/child_document.rb +7 -0
  79. data/spec/internal/log/.gitignore +1 -0
  80. data/spec/presenters/apress/documentation/dependency_presenter_spec.rb +139 -0
  81. data/spec/spec_helper.rb +27 -0
  82. metadata +335 -0
@@ -0,0 +1,19 @@
1
+ p.normal {
2
+ font-weight: normal;
3
+ }
4
+
5
+ p.italic {
6
+ font-style: italic;
7
+ }
8
+
9
+ p.oblique {
10
+ font-style: oblique;
11
+ }
12
+
13
+ p.light {
14
+ font-weight: lighter;
15
+ }
16
+
17
+ p.bold {
18
+ font-weight: bold;
19
+ }
@@ -0,0 +1,9 @@
1
+ @import 'variables';
2
+
3
+ .content {
4
+ padding: 40px 40px 60px;
5
+ width: auto;
6
+ margin-left: $sidebar-width;
7
+ position: relative;
8
+ min-height: calc(100vh - 83px);
9
+ }
@@ -0,0 +1,19 @@
1
+ @import 'variables';
2
+
3
+ .sidebar {
4
+ width: $sidebar-width;
5
+ z-index: 9;
6
+ left: 0;
7
+ position: fixed;
8
+ top: 0;
9
+ height: 100%;
10
+ padding: $sidebar-padding;
11
+ background-color: $sidebar-bg;
12
+ border-right: 1px solid $border-accent-color;
13
+ box-shadow: $box-shadow-accent;
14
+ overflow: scroll;
15
+
16
+ & > ul li {
17
+ margin-left: 6%;
18
+ }
19
+ }
@@ -0,0 +1,3 @@
1
+ .swagger-section .swagger-ui-wrap .info {
2
+ display: none;
3
+ }
@@ -0,0 +1,46 @@
1
+ .switch {
2
+ position: relative; width: 154px;
3
+ user-select: none;
4
+ }
5
+ .switch-checkbox {
6
+ display: none;
7
+ }
8
+ .switch-label {
9
+ display: block; overflow: hidden; cursor: pointer;
10
+ border: 2px solid #999; border-radius: 26px;
11
+ }
12
+ .switch-inner {
13
+ display: block; width: 200%; margin-left: -100%;
14
+ transition: margin .3s ease-in 0s;
15
+ }
16
+ .switch-inner:before,
17
+ .switch-inner:after {
18
+ display: block; float: left; width: 50%; height: 19px; padding: 0; line-height: 19px;
19
+ font-size: 14px; color: #fff; font-family: Trebuchet, Arial, sans-serif; font-weight: bold;
20
+ box-sizing: border-box;
21
+ }
22
+ .switch-inner:before {
23
+ content: 'ВСЕ';
24
+ padding-left: 10px;
25
+ background-color: #34a7c1; color: #fff;
26
+ }
27
+ .switch-inner:after {
28
+ content: 'ДРУГИЕ МОДУЛИ';
29
+ padding-right: 10px;
30
+ background-color: #eee; color: #999;
31
+ text-align: right;
32
+ }
33
+ .switch-switch {
34
+ display: block; width: 17px; margin: 1px;
35
+ background: #fff;
36
+ position: absolute; top: 0; bottom: 0;
37
+ right: 134px;
38
+ border: 2px solid #999; border-radius: 30px;
39
+ transition: all .3s ease-in 0s;
40
+ }
41
+ .switch-checkbox:checked + .switch-label .switch-inner {
42
+ margin-left: 0;
43
+ }
44
+ .switch-checkbox:checked + .switch-label .switch-switch {
45
+ right: 0;
46
+ }
@@ -0,0 +1,26 @@
1
+ // Base
2
+ $body-bg: #fff;
3
+ $font-family: 'Lato', sans-serif;
4
+ $font-family-glyph: fontAwesome;
5
+ $font-family-headings: 'Lato', sans-serif;
6
+ $font-size: 15px;
7
+ $line-height: 1.6;
8
+ $border-accent-color: #f1f1f1;
9
+ $box-shadow-accent: 0 0 0 2px rgba(51, 51, 51, .02);
10
+
11
+ // Grid
12
+ $screen-sm-max: 991px !default;
13
+
14
+ // Heading
15
+ $headings-font-weight: 400;
16
+ $heading-line-heading: 1.1;
17
+ $heading-color: #232323;
18
+
19
+ // Text Colors
20
+ $text-color: #4a4a4a;
21
+ $link-color: #237dac;
22
+
23
+ // Sidebar
24
+ $sidebar-width: 320px;
25
+ $sidebar-bg: #fff;
26
+ $sidebar-padding: 35px;
@@ -0,0 +1,9 @@
1
+ /*
2
+ *= require document/variables
3
+ *= require document/base
4
+ *= require document/layout
5
+ *= require document/sidebar
6
+ *= require document/swagger
7
+ *= require document/document
8
+ *= require document/switch
9
+ */
@@ -0,0 +1,4 @@
1
+ /*
2
+ *= require swagger-ui/dist/css/reset.css
3
+ *= require swagger-ui/dist/css/print.css
4
+ */
@@ -0,0 +1,4 @@
1
+ /*
2
+ *= require swagger-ui/dist/css/reset.css
3
+ *= require swagger-ui/dist/css/screen.css
4
+ */
@@ -0,0 +1,14 @@
1
+ module Apress
2
+ module Documentation
3
+ class DocumentsController < ActionController::Base
4
+ include ::Apress::Documentation::PreloadDocs
5
+ layout 'documentation'
6
+
7
+ def show
8
+ @document = Apress::Documentation.fetch_document(params[:path]) if params[:path]
9
+ end
10
+
11
+ ActiveSupport.run_load_hooks(:'apress/documentation/documents_controller', self)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,22 @@
1
+ module Apress
2
+ module Documentation
3
+ class SwaggerController < ::ActionController::Base
4
+ include ::Apress::Documentation::PreloadDocs
5
+
6
+ def show
7
+ service = Apress::Documentation::SwaggerJsonBuilder.new(params[:slug])
8
+ data =
9
+ if Rails.application.config.action_controller.perform_caching
10
+ key = ActiveSupport::Cache.expand_cache_key(["swagger_schema", params[:slug]])
11
+ Rails.cache.fetch(key) { service.call }
12
+ else
13
+ service.call
14
+ end
15
+
16
+ render json: data
17
+ end
18
+
19
+ ActiveSupport.run_load_hooks(:'apress/documentation/swagger_controller', self)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,11 @@
1
+ module Apress
2
+ module Documentation
3
+ class SwaggerUiController < ::ActionController::Base
4
+ def show
5
+ render 'show', layout: false
6
+ end
7
+
8
+ ActiveSupport.run_load_hooks(:'apress/documentation/swagger_ui_controller', self)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,20 @@
1
+ module Apress
2
+ module Documentation
3
+ module PreloadDocs
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ if (Rails::VERSION::MAJOR == 4 && Rails::VERSION::MINOR == 2) || Rails::VERSION::MAJOR > 4
8
+ before_action :load_docs
9
+ else
10
+ before_filter :load_docs
11
+ end
12
+ end
13
+
14
+ def load_docs
15
+ ActiveSupport.run_load_hooks(:documentation)
16
+ Apress::Documentation.validate_dependencies!
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,14 @@
1
+ module Apress
2
+ module Documentation
3
+ module DocumentsHelper
4
+ def document_url_with_swagger(document)
5
+ if document.is_a?(Apress::Documentation::Storage::SwaggerDocument)
6
+ js_path = "#!/#{document.tag}/#{document.operation_id}"
7
+ documentation_url(path: document.document.slug.to_s) + js_path
8
+ else
9
+ documentation_url(path: document.slug.to_s)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,75 @@
1
+ module Apress
2
+ module Documentation
3
+ class DependencyPresenter
4
+ def initialize(view, document)
5
+ @view = view
6
+ @document = document
7
+ end
8
+
9
+ def render_deps(reverse: false)
10
+ @view.render(
11
+ 'apress/documentation/presenters/dependency_presenter/dependencies',
12
+ dependencies: dependencies(reverse: reverse),
13
+ all_dependencies: all_dependencies(reverse: reverse),
14
+ current_document: @document
15
+ )
16
+ end
17
+
18
+ private
19
+
20
+ # Private: определяет зависимости из других модулей для @document и его потомков
21
+ #
22
+ # Arguments:
23
+ # reverse - см - Apress::Documentation::Storage::BaseStorage::dependencies
24
+ #
25
+ # Returns Array of Pairs [[doc, depend_doc], [doc_3, depend_doc]
26
+ def dependencies(reverse: false)
27
+ all_dependencies(reverse: reverse).select do |from, to|
28
+ from.current_module != @document.current_module ||
29
+ to.current_module != @document.current_module
30
+ end
31
+ end
32
+
33
+ # Private: определяет все зависимости для @document и его потомков
34
+ #
35
+ # Arguments:
36
+ # reverse - см - Apress::Documentation::Storage::BaseStorage::dependencies
37
+ #
38
+ # Returns Array of Pairs [[doc, depend_doc], [doc_3, depend_doc]
39
+ def all_dependencies(reverse: false)
40
+ @dependencies ||= Hash.new do |h, key|
41
+ h[key] = @document.dependencies(reverse: key)
42
+ h[key] = child_dependencies(@document, reverse: key) if h[key].blank?
43
+ h[key]
44
+ end
45
+
46
+ @dependencies[reverse]
47
+ end
48
+
49
+ # Private: рекурсивно находит все зависимости среди потомков document
50
+ #
51
+ # Arguments:
52
+ # document - (Document) - документ для которого ищем зависимости
53
+ # reverse - см - Apress::Documentation::Storage::BaseStorage::dependencies
54
+ #
55
+ # Returns Array of Pairs [[doc, depend_doc], [doc_3, depend_doc]
56
+ def child_dependencies(document, reverse: false)
57
+ unless document.respond_to?(:documents)
58
+ return document.dependencies(reverse: reverse)
59
+ end
60
+
61
+ child_deps = document.documents.inject([]) do |deps, (_, doc)|
62
+ deps.concat(child_dependencies(doc, reverse: reverse))
63
+ end
64
+
65
+ document.swagger_documents.inject(child_deps) do |deps, (_, doc)|
66
+ deps.concat(doc.dependencies(reverse: reverse))
67
+ end
68
+
69
+ child_deps.concat(document.dependencies(reverse: reverse))
70
+
71
+ child_deps
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,22 @@
1
+ module Apress
2
+ module Documentation
3
+ class SwaggerJsonBuilder
4
+ def initialize(module_name)
5
+ @module_name = module_name
6
+ end
7
+
8
+ def call
9
+ classes =
10
+ if @module_name
11
+ Apress::Documentation::Swagger::Schema.swagger_classes.select do |klass|
12
+ klass.document_slug.to_s == @module_name.to_s || !klass.resource
13
+ end
14
+ else
15
+ Apress::Documentation::Swagger::Schema.swagger_classes
16
+ end
17
+
18
+ ::Swagger::Blocks.build_root_json(classes)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,32 @@
1
+ %h1
2
+ = document.title.to_s.html_safe || document.slug.to_s.html_safe
3
+
4
+ %h3 Описание
5
+ %p
6
+ = (document.description || "Нет данных").to_s.html_safe
7
+
8
+ %h3 Бизнесс описание
9
+ %p
10
+ = (document.business_desc || "Нет данных").to_s.html_safe
11
+
12
+ %h3 Публичность
13
+ %p
14
+ = (document.publicity || "Нет данных").to_s.html_safe
15
+
16
+ %h3 Тесты
17
+ %p
18
+ = (document.tests || "Нет данных").to_s.html_safe
19
+
20
+ %h3 Зависимости
21
+ .js-dependencies-container
22
+ .switch
23
+ %input.switch-checkbox.js-dependency-switch{type: "checkbox", id: "doc-switch"}
24
+ %label.switch-label{for: "doc-switch"}
25
+ %span.switch-inner
26
+ %span.switch-switch
27
+
28
+ %h4 Зависит от
29
+ != Apress::Documentation::DependencyPresenter.new(self, document).render_deps
30
+
31
+ %h4 Используется в
32
+ != Apress::Documentation::DependencyPresenter.new(self, document).render_deps(reverse: true)
@@ -0,0 +1,10 @@
1
+ .swagger-section
2
+ .swagger-ui-wrap{id: "swagger-ui-container"}
3
+
4
+ :javascript
5
+ app.swagger = {
6
+ "docsUrl": "#{docs_path(slug: document.slug)}",
7
+ "docsExpansion": "list"
8
+ };
9
+
10
+ app.extensions = #{document.swagger_documents.to_json(view: self)};
@@ -0,0 +1,13 @@
1
+ = cache ['documentation', params[:path]] do
2
+ - if @document
3
+ - if @document.swagger?
4
+ = render 'swagger', document: @document
5
+ - else
6
+ = render 'document', document: @document
7
+
8
+ - else
9
+ %h1 Документация АБАК-ПРЕСС
10
+ %p
11
+ Данный ресурс содержит все описания модулей и контрактов разработанных в АБАК-ПРЕСС.
12
+ Подробную информацию о устройстве системы можно найти в геме
13
+ %a{href: "https://github.com/abak-press/apress-documentation"}apress-documentation.
@@ -0,0 +1,21 @@
1
+ :ruby
2
+ all_dependencies = local_assigns.fetch(:all_dependencies)
3
+ current_document = local_assigns.fetch(:current_document)
4
+ dependencies = local_assigns.fetch(:dependencies)
5
+
6
+ .dependencies-container
7
+ - if dependencies.present?
8
+ .js-dependencies
9
+ - dependencies.each do |contract_def, dep|
10
+ = render 'apress/documentation/presenters/dependency_presenter/links',
11
+ dependency: dep,
12
+ contract_def: contract_def,
13
+ current_document: current_document
14
+
15
+ - if all_dependencies.present?
16
+ .js-all-dependencies.hidden
17
+ - all_dependencies.each do |contract_def, dep|
18
+ = render 'apress/documentation/presenters/dependency_presenter/links',
19
+ dependency: dep,
20
+ contract_def: contract_def,
21
+ current_document: current_document
@@ -0,0 +1,17 @@
1
+ :ruby
2
+ dependency = local_assigns.fetch(:dependency)
3
+ contract_def = local_assigns.fetch(:contract_def)
4
+ current_document = local_assigns.fetch(:current_document)
5
+ title =
6
+ if dependency.title
7
+ dependency.current_module.title.to_s + "::" + dependency.title .to_s
8
+ else
9
+ dependency.slug
10
+ end
11
+
12
+ .link
13
+ = link_to title, document_url_with_swagger(dependency)
14
+ - if contract_def != current_document
15
+ = "("
16
+ = link_to(contract_def.title || contract_def.slug, document_url_with_swagger(contract_def))
17
+ = ")"
@@ -0,0 +1,26 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ = stylesheet_link_tag 'package/swagger_screen', media: :screen
5
+ = stylesheet_link_tag 'package/swagger_print', media: :print
6
+ = javascript_include_tag 'package/documentation', defer: true
7
+ :javascript
8
+ var app = {
9
+ "swagger": {
10
+ "docsUrl": "#{docs_path}"
11
+ }
12
+ }
13
+
14
+
15
+ %body.swagger-section
16
+ .header
17
+ .swagger-ui-wrap
18
+ %form{id: 'api_selector'}
19
+ .input
20
+ %input{placeholder: "http://example.com/api", id: "input_baseUrl", name: "baseUrl", type: "text"}
21
+ .auth_container
22
+ .input
23
+ %a.header__btn{id: "explore", href: "#"}
24
+ Explore
25
+ .swagger-ui-wrap{id: 'message-bar'}
26
+ .swagger-ui-wrap{id: "swagger-ui-container"}