utopia-project 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +13 -0
  3. data/.github/workflows/development.yml +62 -0
  4. data/.gitignore +17 -0
  5. data/.rspec +2 -0
  6. data/.yarnrc +1 -0
  7. data/README.md +41 -0
  8. data/bake/utopia/project.rb +32 -0
  9. data/gems.rb +4 -0
  10. data/guides/documentation-formatting/README.md +55 -0
  11. data/guides/github-pages-integration/README.md +17 -0
  12. data/lib/utopia/project/base.rb +167 -0
  13. data/lib/utopia/project/guide.rb +131 -0
  14. data/lib/utopia/project/version.rb +27 -0
  15. data/lib/utopia/project.rb +98 -0
  16. data/package.json +6 -0
  17. data/pages/_heading.xnode +3 -0
  18. data/pages/_navigation.xnode +23 -0
  19. data/pages/_page.xnode +32 -0
  20. data/pages/_thumbnail.xnode +8 -0
  21. data/pages/_usage.xnode +21 -0
  22. data/pages/controller.rb +29 -0
  23. data/pages/errors/exception.xnode +5 -0
  24. data/pages/errors/file-not-found.xnode +5 -0
  25. data/pages/guides/controller.rb +18 -0
  26. data/pages/guides/index.xnode +17 -0
  27. data/pages/guides/show.xnode +24 -0
  28. data/pages/index.xnode +9 -0
  29. data/pages/links.yaml +4 -0
  30. data/pages/source/controller.rb +18 -0
  31. data/pages/source/index.xnode +34 -0
  32. data/pages/source/show.xnode +63 -0
  33. data/public/.nojekyll +0 -0
  34. data/public/_components/jquery/jquery.js +10872 -0
  35. data/public/_components/jquery/jquery.min.js +2 -0
  36. data/public/_components/jquery/jquery.min.map +1 -0
  37. data/public/_components/jquery/jquery.slim.js +8777 -0
  38. data/public/_components/jquery/jquery.slim.min.js +2 -0
  39. data/public/_components/jquery/jquery.slim.min.map +1 -0
  40. data/public/_components/jquery-litebox/jquery.litebox.css +23 -0
  41. data/public/_components/jquery-litebox/jquery.litebox.gallery.css +48 -0
  42. data/public/_components/jquery-litebox/jquery.litebox.js +30 -0
  43. data/public/_components/jquery-syntax/base/jquery.syntax.brush.apache.css +12 -0
  44. data/public/_components/jquery-syntax/base/jquery.syntax.brush.applescript.css +5 -0
  45. data/public/_components/jquery-syntax/base/jquery.syntax.brush.assembly.css +8 -0
  46. data/public/_components/jquery-syntax/base/jquery.syntax.brush.bash-script.css +6 -0
  47. data/public/_components/jquery-syntax/base/jquery.syntax.brush.bash.css +4 -0
  48. data/public/_components/jquery-syntax/base/jquery.syntax.brush.clang.css +6 -0
  49. data/public/_components/jquery-syntax/base/jquery.syntax.brush.css.css +14 -0
  50. data/public/_components/jquery-syntax/base/jquery.syntax.brush.diff.css +16 -0
  51. data/public/_components/jquery-syntax/base/jquery.syntax.brush.html.css +5 -0
  52. data/public/_components/jquery-syntax/base/jquery.syntax.brush.ocaml.css +3 -0
  53. data/public/_components/jquery-syntax/base/jquery.syntax.brush.protobuf.css +2 -0
  54. data/public/_components/jquery-syntax/base/jquery.syntax.brush.python.css +6 -0
  55. data/public/_components/jquery-syntax/base/jquery.syntax.brush.ruby.css +2 -0
  56. data/public/_components/jquery-syntax/base/jquery.syntax.brush.xml.css +18 -0
  57. data/public/_components/jquery-syntax/base/jquery.syntax.core.css +58 -0
  58. data/public/_components/jquery-syntax/base/jquery.syntax.editor.css +6 -0
  59. data/public/_components/jquery-syntax/base/theme.js +1 -0
  60. data/public/_components/jquery-syntax/bright/jquery.syntax.core.css +27 -0
  61. data/public/_components/jquery-syntax/bright/theme.js +1 -0
  62. data/public/_components/jquery-syntax/jquery.syntax.brush.apache.js +3 -0
  63. data/public/_components/jquery-syntax/jquery.syntax.brush.applescript.js +5 -0
  64. data/public/_components/jquery-syntax/jquery.syntax.brush.assembly.js +3 -0
  65. data/public/_components/jquery-syntax/jquery.syntax.brush.bash-script.js +4 -0
  66. data/public/_components/jquery-syntax/jquery.syntax.brush.bash.js +2 -0
  67. data/public/_components/jquery-syntax/jquery.syntax.brush.basic.js +5 -0
  68. data/public/_components/jquery-syntax/jquery.syntax.brush.clang.js +5 -0
  69. data/public/_components/jquery-syntax/jquery.syntax.brush.csharp.js +4 -0
  70. data/public/_components/jquery-syntax/jquery.syntax.brush.css.js +5 -0
  71. data/public/_components/jquery-syntax/jquery.syntax.brush.diff.js +2 -0
  72. data/public/_components/jquery-syntax/jquery.syntax.brush.go.js +3 -0
  73. data/public/_components/jquery-syntax/jquery.syntax.brush.haskell.js +3 -0
  74. data/public/_components/jquery-syntax/jquery.syntax.brush.html.js +4 -0
  75. data/public/_components/jquery-syntax/jquery.syntax.brush.io.js +3 -0
  76. data/public/_components/jquery-syntax/jquery.syntax.brush.java.js +4 -0
  77. data/public/_components/jquery-syntax/jquery.syntax.brush.javascript.js +3 -0
  78. data/public/_components/jquery-syntax/jquery.syntax.brush.kai.js +2 -0
  79. data/public/_components/jquery-syntax/jquery.syntax.brush.lisp.js +2 -0
  80. data/public/_components/jquery-syntax/jquery.syntax.brush.lua.js +3 -0
  81. data/public/_components/jquery-syntax/jquery.syntax.brush.nginx.js +2 -0
  82. data/public/_components/jquery-syntax/jquery.syntax.brush.ocaml.js +4 -0
  83. data/public/_components/jquery-syntax/jquery.syntax.brush.ooc.js +4 -0
  84. data/public/_components/jquery-syntax/jquery.syntax.brush.pascal.js +4 -0
  85. data/public/_components/jquery-syntax/jquery.syntax.brush.perl5.js +3 -0
  86. data/public/_components/jquery-syntax/jquery.syntax.brush.php-script.js +4 -0
  87. data/public/_components/jquery-syntax/jquery.syntax.brush.php.js +2 -0
  88. data/public/_components/jquery-syntax/jquery.syntax.brush.plain.js +2 -0
  89. data/public/_components/jquery-syntax/jquery.syntax.brush.protobuf.js +3 -0
  90. data/public/_components/jquery-syntax/jquery.syntax.brush.python.js +5 -0
  91. data/public/_components/jquery-syntax/jquery.syntax.brush.ruby.js +5 -0
  92. data/public/_components/jquery-syntax/jquery.syntax.brush.scala.js +4 -0
  93. data/public/_components/jquery-syntax/jquery.syntax.brush.smalltalk.js +2 -0
  94. data/public/_components/jquery-syntax/jquery.syntax.brush.sql.js +4 -0
  95. data/public/_components/jquery-syntax/jquery.syntax.brush.super-collider.js +3 -0
  96. data/public/_components/jquery-syntax/jquery.syntax.brush.swift.js +3 -0
  97. data/public/_components/jquery-syntax/jquery.syntax.brush.trenni.js +2 -0
  98. data/public/_components/jquery-syntax/jquery.syntax.brush.xml.js +4 -0
  99. data/public/_components/jquery-syntax/jquery.syntax.brush.yaml.js +2 -0
  100. data/public/_components/jquery-syntax/jquery.syntax.cache.js +7 -0
  101. data/public/_components/jquery-syntax/jquery.syntax.core.js +34 -0
  102. data/public/_components/jquery-syntax/jquery.syntax.editor.js +11 -0
  103. data/public/_components/jquery-syntax/jquery.syntax.js +8 -0
  104. data/public/_components/jquery-syntax/jquery.syntax.min.js +13 -0
  105. data/public/_components/jquery-syntax/paper/jquery.syntax.core.css +31 -0
  106. data/public/_components/jquery-syntax/paper/theme.js +1 -0
  107. data/public/_static/icon.png +0 -0
  108. data/public/_static/site.css +197 -0
  109. data/template/Gemfile +6 -0
  110. data/template/config.ru +6 -0
  111. data/template/preload.rb +2 -0
  112. data/utopia-project.gemspec +38 -0
  113. data/yarn.lock +22 -0
  114. metadata +351 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6aa72e7117031702241752a366174d7bc8fa7a44ca0bbf52de399ef9c89173e4
4
+ data.tar.gz: b32f8ef78c132cfcb4cd414416aa0c7dd547e9253a989565f3446027003b55ef
5
+ SHA512:
6
+ metadata.gz: 582d3f3051f7f0a304b4bf1c286eb22fc45bc9b8a87ef3cb5f51740553608cbef88a4d1d0db5cb442acc1d101884f4eb020e34e47c4fc466b47ca4bb312b7b9a
7
+ data.tar.gz: 264853fea075ef9d3f1b1787a3b9bd3c6f42364bb29378efbbbb6f9e501eb366655f4df26fbf740b74c02ff58e96560d21ae444909afb3e52eeb186929ba3879
data/.editorconfig ADDED
@@ -0,0 +1,13 @@
1
+ root = true
2
+
3
+ [*]
4
+ indent_style = tab
5
+ indent_size = 2
6
+
7
+ [*.md]
8
+ indent_style = tab
9
+ indent_size = 2
10
+
11
+ [.*]
12
+ indent_style = tab
13
+ indent_size = 2
@@ -0,0 +1,62 @@
1
+ name: Development
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ test:
7
+ runs-on: ${{matrix.os}}-latest
8
+ continue-on-error: ${{matrix.experimental}}
9
+
10
+ strategy:
11
+ matrix:
12
+ os:
13
+ - ubuntu
14
+ - macos
15
+
16
+ ruby:
17
+ - 2.5
18
+ - 2.6
19
+ - 2.7
20
+
21
+ experimental: [false]
22
+ env: [""]
23
+
24
+ include:
25
+ - os: ubuntu
26
+ ruby: truffleruby
27
+ experimental: true
28
+ env: JRUBY_OPTS="--debug -X+O"
29
+ - os: ubuntu
30
+ ruby: jruby
31
+ experimental: true
32
+ - os: ubuntu
33
+ ruby: head
34
+ experimental: true
35
+ - os: ubuntu
36
+ ruby: 2.6
37
+ experimental: false
38
+ env: COVERAGE=PartialSummary,Coveralls
39
+
40
+ steps:
41
+ - uses: actions/checkout@v1
42
+ - uses: ruby/setup-ruby@v1
43
+ with:
44
+ ruby-version: ${{matrix.ruby}}
45
+
46
+ - name: Installing packages (ubuntu)
47
+ if: matrix.os == 'ubuntu'
48
+ run: sudo apt-get install wget pkg-config
49
+
50
+ - name: Installing packages (macos)
51
+ if: matrix.os == 'macos'
52
+ run: brew install wget pkg-config
53
+
54
+ - name: Install dependencies
55
+ run: ${{matrix.env}} bundle install
56
+
57
+ - name: Run tests
58
+ timeout-minutes: 5
59
+ run: |
60
+ git config --global user.email "samuel@oriontransfer.net"
61
+ git config --global user.name "Samuel Williams"
62
+ ${{matrix.env}} bundle exec rspec
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ # Development specific:
2
+ /.rspec_status
3
+ /.bundle
4
+ /pkg
5
+ /gems.locked
6
+
7
+ # Temporary data should not be added to the repository:
8
+ /tmp
9
+
10
+ # Node modules are 3rd party dependencies which can be fetched easily:
11
+ /node_modules
12
+
13
+ # This file should only ever exist on production, and may contain sensitive information:
14
+ /config/environment.yaml
15
+
16
+ # Ignore resized gallery photos:
17
+ /public/_gallery
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --require spec_helper
data/.yarnrc ADDED
@@ -0,0 +1 @@
1
+ --modules-folder lib/components
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # Utopia::Project
2
+
3
+ A simple Ruby project documentation website.
4
+
5
+ ## Usage
6
+
7
+ Please see the <a href="https://socketry.github.io/utopia-project/">project documentation</a> or run it locally using `bake utopia:project:serve`.
8
+
9
+ ## Contributing
10
+
11
+ We welcome contributions to this project.
12
+
13
+ 1. Fork it
14
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
15
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
16
+ 4. Push to the branch (`git push origin my-new-feature`)
17
+ 5. Create new Pull Request
18
+
19
+ ## License
20
+
21
+ Released under the MIT license.
22
+
23
+ Copyright, 2020, by [Samuel G. D. Williams](http://www.codeotaku.com).
24
+
25
+ Permission is hereby granted, free of charge, to any person obtaining a copy
26
+ of this software and associated documentation files (the "Software"), to deal
27
+ in the Software without restriction, including without limitation the rights
28
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
29
+ copies of the Software, and to permit persons to whom the Software is
30
+ furnished to do so, subject to the following conditions:
31
+
32
+ The above copyright notice and this permission notice shall be included in
33
+ all copies or substantial portions of the Software.
34
+
35
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
36
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
37
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
38
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
39
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
40
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
41
+ THE SOFTWARE.
@@ -0,0 +1,32 @@
1
+
2
+ # Create an empty project in the current directory.
3
+ def create
4
+ template_path = File.expand_path("../../template/*", __dir__)
5
+
6
+ Dir.glob(template_path) do |path|
7
+ FileUtils::Verbose.cp_r path, Dir.pwd
8
+ end
9
+ end
10
+
11
+ # Serve the project locally.
12
+ def serve
13
+ config_path = File.expand_path("../../template/config.ru", __dir__)
14
+ preload_path = File.expand_path("../../template/preload.rb", __dir__)
15
+
16
+ system("falcon", "serve", "--config", config_path, "--preload", preload_path)
17
+ end
18
+
19
+ def static(output_path: "docs")
20
+ require 'rackula/command'
21
+
22
+ config_path = File.expand_path("../../template/config.ru", __dir__)
23
+ public_path = File.expand_path("../../public", __dir__)
24
+
25
+ Rackula::Command::Top["generate", "--force",
26
+ "--config", config_path,
27
+ "--public", public_path,
28
+ "--output-path", output_path
29
+ ].call
30
+
31
+ FileUtils.touch File.expand_path(".nojekyll", output_path)
32
+ end
data/gems.rb ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in utopia-project.gemspec
4
+ gemspec
@@ -0,0 +1,55 @@
1
+ # Documentation Formatting
2
+
3
+ This guide explains the conventions used by `utopia-project` when generating documentation for your project.
4
+
5
+ ## Source Code Documentation
6
+
7
+ Source code documentation is expected to be in markdown format. This is different from the canonical `RDoc` format used by Ruby. However, using markdown is a good format for standardised documentation across a range of different languages.
8
+
9
+ ### Tags
10
+
11
+ #### `@param`
12
+
13
+ The `@param` tag is used to describe the parameters of a method:
14
+
15
+ ~~~ ruby
16
+ # @param x [Integer] The x co-ordinate.
17
+ # @param y [Integer] The y co-ordinate.
18
+ def move(x, y)
19
+ # ...
20
+ end
21
+ ~~~
22
+
23
+ #### `@return`
24
+
25
+ The `@return` tag is used to describe the return type of the definition:
26
+
27
+ ~~~ ruby
28
+ # @return [Integer] The result of the computation.
29
+ def fib(n)
30
+ # ...
31
+ end
32
+ ~~~
33
+
34
+ ### References
35
+
36
+ It is possible to insert references in your documentation using curly brackets. In the following example `{Input}` will be expanded relative to the usage, to some symbol named `Input`.
37
+
38
+ ~~~ ruby
39
+ # Frobulates the input, see {Input} for more details.
40
+ def frobulate(input)
41
+ # ... left to the imagination ...
42
+ end
43
+ ~~~
44
+
45
+ ## Examples & Guides
46
+
47
+ Examples provide structured information to help users understand your project and are located in the `examples/` directory. One sub-directory per example.
48
+
49
+ ### `README.md`
50
+
51
+ If an example has a `README.md` file, it is used as the main source of documentation.
52
+
53
+ ### Source Files
54
+
55
+ All other source files are listed on the example page. Top level comments with trailing code (segments) are used to help guide the user through the example.
@@ -0,0 +1,17 @@
1
+ # GitHub Pages Integration
2
+
3
+ This guide shows you how to use `utopia-project` with GitHub Pages.
4
+
5
+ ## Static Site Generation
6
+
7
+ Once you are happy with your project's documentation, simply generate a static site:
8
+
9
+ ~~~ bash
10
+ $ bake utopia:project:static
11
+ ~~~
12
+
13
+ This will generate a static copy of your documentation into `docs/` which is what is required by GitHub Pages.
14
+
15
+ ## Enable GitHub Pages
16
+
17
+ In your GitHub project settings, you will need to [enable GitHub Pages served from `docs/`](https://help.github.com/en/github/working-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#choosing-a-publishing-source).
@@ -0,0 +1,167 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright, 2020, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require 'utopia/path'
24
+ require 'trenni/reference'
25
+ require 'decode'
26
+
27
+ require 'thread/local'
28
+
29
+ require 'kramdown'
30
+
31
+ require_relative 'guide'
32
+
33
+ module Utopia
34
+ module Project
35
+ # The base symbol table and project index.
36
+ class Base
37
+ extend Thread::Local
38
+
39
+ def self.local
40
+ instance = self.new
41
+
42
+ source_files = Dir.glob(
43
+ File.expand_path("lib/**/*.rb", instance.root)
44
+ )
45
+
46
+ instance.update(source_files)
47
+
48
+ return instance
49
+ end
50
+
51
+ # Initialize the project with the given root path.
52
+ # @param root [String] The file-system path to the root of the project.
53
+ def initialize(root = Dir.pwd)
54
+ @root = root
55
+
56
+ @source_path = Utopia::Path["/source"]
57
+
58
+ @index = Decode::Index.new
59
+ end
60
+
61
+ # The file-system path to the root of the project.
62
+ attr :root
63
+
64
+ # The source code index which is used for generating pages.
65
+ attr :index
66
+
67
+ # Return the absolute path for the given file name, if it exists in the project.
68
+ # @param file_name [String] The relative path to the project file, e.g. `README.md`.
69
+ def path_for(file_name)
70
+ full_path = File.expand_path(file_name, @root)
71
+ if File.exist?(full_path)
72
+ return full_path
73
+ end
74
+ end
75
+
76
+ # Update the index with the specified paths.
77
+ # @param paths [Array(String)] The paths to load and parse.
78
+ def update(paths)
79
+ @index.update(paths)
80
+ end
81
+
82
+ def best(symbols)
83
+ symbols.each do |symbol|
84
+ if symbol.documentation
85
+ return symbol
86
+ end
87
+ end
88
+
89
+ return symbols.first
90
+ end
91
+
92
+ def lookup(path)
93
+ if node = @index.trie.lookup(path.map(&:to_sym))
94
+ return node, best(node.values)
95
+ end
96
+ end
97
+
98
+ def format(text, symbol = nil, language: symbol&.language)
99
+ if text.is_a?(Enumerable)
100
+ text = text.to_a.join("\n")
101
+ end
102
+
103
+ if language
104
+ text = text&.gsub(/{(.*?)}/) do |match|
105
+ linkify($1, symbol, language: language)
106
+ end
107
+ end
108
+
109
+ return Trenni::MarkupString.raw(
110
+ Kramdown::Document.new(text, syntax_highlighter: nil).to_html
111
+ )
112
+ end
113
+
114
+ def linkify(text, symbol = nil, language: symbol&.language)
115
+ reference = language.reference(text)
116
+
117
+ Trenni::Builder.fragment do |builder|
118
+ if definition = @index.lookup(reference, relative_to: symbol)&.first
119
+ builder.inline('a', href: link_for(definition)) do
120
+ builder.inline('code', class: "language-#{definition.language.name}") do
121
+ builder.text definition.short_form
122
+ end
123
+ end
124
+ else
125
+ builder.inline('code', class: "language-#{symbol.language.name}") do
126
+ builder.text text
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ # Compute a unique string which can be used as `id` attribute in the HTML output.
133
+ def id_for(symbol)
134
+ symbol.qualified_name
135
+ end
136
+
137
+ # Compute a link href to the given symbol for use within the HTML output.
138
+ def link_for(symbol)
139
+ path = symbol.lexical_path.map{|entry| entry.to_s}
140
+
141
+ if symbol.container?
142
+ return Trenni::Reference.new(@source_path + path + "index")
143
+ else
144
+ name = path.pop
145
+ return Trenni::Reference.new(@source_path + path + "index", fragment: id_for(symbol))
146
+ end
147
+ end
148
+
149
+ def guides
150
+ guides_root = File.expand_path("guides", @root)
151
+
152
+ # There are no guides if there is no directory:
153
+ return unless File.directory?(guides_root)
154
+
155
+ return to_enum(:guides) unless block_given?
156
+
157
+ Dir.each_child(guides_root) do |entry|
158
+ guide_path = File.join(guides_root, entry)
159
+
160
+ next unless File.directory?(guide_path)
161
+
162
+ yield Guide.new(self, guide_path)
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
@@ -0,0 +1,131 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright, 2020, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require 'utopia/path'
24
+ require 'trenni/reference'
25
+ require 'decode'
26
+ require 'kramdown'
27
+
28
+ module Utopia
29
+ module Project
30
+ class Guide
31
+ # Initialize the example with the given root path.
32
+ # @param base [Base] The base instance for the project.
33
+ # @param root [String] The file-system path to the root of the example.
34
+ def initialize(base, root)
35
+ @base = base
36
+ @root = root
37
+
38
+ @documentation = nil
39
+
40
+ @document = nil
41
+ @title = nil
42
+ @description = nil
43
+
44
+ self.document
45
+ end
46
+
47
+ # The description from the first paragraph in the README.
48
+ # @attr [String | Nil]
49
+ attr :description
50
+
51
+ README = "README.md"
52
+
53
+ def readme_path
54
+ File.expand_path(README, @root)
55
+ end
56
+
57
+ def readme?
58
+ File.exist?(readme_path)
59
+ end
60
+
61
+ def document
62
+ if self.readme?
63
+ @document ||= Kramdown::Document.new(File.read(self.readme_path), syntax_highlighter: nil).tap do |document|
64
+ root = document.root
65
+ if element = root.children.first
66
+ if element.type == :header
67
+ @title = element.children.first.value
68
+
69
+ # Remove the title:
70
+ root.children.shift
71
+
72
+ # Remove any blank lines:
73
+ root.children.shift while root.children.first&.type == :blank
74
+
75
+ # Read the description:
76
+ root.children.first.options[:encoding] = root.options[:encoding]
77
+ @description = Kramdown::Converter::Kramdown.convert(root.children.first).first
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ # The base instance of the project this example is loaded from.
85
+ attr :base
86
+
87
+ # The file-system path to the root of the project.
88
+ attr :root
89
+
90
+ def name
91
+ File.basename(@root)
92
+ end
93
+
94
+ def title
95
+ @title || Trenni::Strings.to_title(self.name)
96
+ end
97
+
98
+ def href
99
+ "/guides/#{self.name}/index"
100
+ end
101
+
102
+ def documentation
103
+ @documentation ||= self.best_documentation
104
+ end
105
+
106
+ def files
107
+ Dir.glob(File.expand_path("*", @root))
108
+ end
109
+
110
+ def sources
111
+ return to_enum(:sources) unless block_given?
112
+
113
+ files.each do |path|
114
+ if source = Decode::Source.for?(path)
115
+ yield source
116
+ end
117
+ end
118
+ end
119
+
120
+ private
121
+
122
+ def best_documentation
123
+ if source = sources.first
124
+ if segment = source.segments.first
125
+ return segment.documentation
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright, 2020, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ module Utopia
24
+ module Project
25
+ VERSION = "0.1.0"
26
+ end
27
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright, 2020, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ require "utopia/project/version"
24
+
25
+ require 'variant'
26
+
27
+ require 'utopia/localization'
28
+ require 'utopia/gallery'
29
+
30
+ require_relative 'project/base'
31
+
32
+ module Utopia
33
+ module Project
34
+ # The root directory of the web application files.
35
+ SITE_ROOT = File.expand_path("../..", __dir__)
36
+
37
+ # The root directory for the utopia middleware.
38
+ PAGES_ROOT = File.expand_path("pages", SITE_ROOT)
39
+
40
+ # The root directory for static assets.
41
+ PUBLIC_ROOT = File.expand_path("public", SITE_ROOT)
42
+
43
+ # Appends a project application to the rack builder.
44
+ #
45
+ # ~~~ ruby
46
+ # # In your `config.ru` file:
47
+ #
48
+ # require 'utopia/setup'
49
+ # UTOPIA ||= Utopia.setup
50
+ #
51
+ # require 'utopia/project'
52
+ # Utopia::Project.call(self)
53
+ # ~~~
54
+ #
55
+ # @param locales [Array(String)] an array of locales to support, e.g. `['en', 'ja']`.
56
+ def self.call(builder, root = Dir.pwd, locales: nil)
57
+ if UTOPIA.production?
58
+ # Handle exceptions in production with a error page and send an email notification:
59
+ builder.use Utopia::Exceptions::Handler
60
+ builder.use Utopia::Exceptions::Mailer
61
+ else
62
+ # We want to propate exceptions up when running tests:
63
+ builder.use Rack::ShowExceptions unless UTOPIA.testing?
64
+ end
65
+
66
+ public_root = File.expand_path("public", root)
67
+ builder.use Utopia::Static, root: public_root
68
+
69
+ builder.use Utopia::Static, root: PUBLIC_ROOT
70
+
71
+ builder.use Utopia::Redirection::Rewrite, {
72
+ '/' => '/index'
73
+ }
74
+
75
+ builder.use Utopia::Redirection::DirectoryIndex
76
+
77
+ builder.use Utopia::Redirection::Errors, {
78
+ 404 => '/errors/file-not-found'
79
+ }
80
+
81
+ if locales
82
+ builder.use Utopia::Localization,
83
+ default_locale: locales.first,
84
+ locales: locales
85
+ end
86
+
87
+ builder.use Utopia::Controller, root: PAGES_ROOT
88
+
89
+ cache_root = File.expand_path("_gallery", root)
90
+
91
+ builder.use Utopia::Content, root: PAGES_ROOT, namespaces: {
92
+ 'gallery' => Utopia::Gallery::Tags.new
93
+ }
94
+
95
+ builder.run lambda { |env| [404, {}, []] }
96
+ end
97
+ end
98
+ end
data/package.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "dependencies": {
3
+ "jquery-litebox": "^1.0.2",
4
+ "jquery-syntax": "^4.1.1"
5
+ }
6
+ }