json-schema-docs 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +48 -9
- data/Rakefile +1 -8
- data/json-schema-docs.gemspec +11 -0
- data/lib/json-schema-docs.rb +1 -0
- data/lib/json-schema-docs/configuration.rb +25 -2
- data/lib/json-schema-docs/generator.rb +93 -21
- data/lib/json-schema-docs/helpers.rb +17 -1
- data/lib/json-schema-docs/landing_pages/index.md +7 -0
- data/lib/json-schema-docs/layouts/assets/_sass/_content.scss +518 -0
- data/lib/json-schema-docs/layouts/assets/_sass/_header.scss +59 -0
- data/lib/json-schema-docs/layouts/assets/_sass/_links.scss +33 -0
- data/lib/json-schema-docs/layouts/assets/_sass/_normalize.scss +127 -0
- data/lib/json-schema-docs/layouts/assets/_sass/_resource.scss +23 -0
- data/lib/json-schema-docs/layouts/assets/_sass/_sidebar.scss +75 -0
- data/lib/json-schema-docs/layouts/assets/css/screen.scss +32 -0
- data/lib/json-schema-docs/layouts/default.html.erb +43 -0
- data/lib/json-schema-docs/layouts/includes/{example.md.erb → curl_example.html.erb} +3 -3
- data/lib/json-schema-docs/layouts/includes/resource_example.html.erb +3 -0
- data/lib/json-schema-docs/layouts/includes/{response.md.erb → response.html.erb} +5 -5
- data/lib/json-schema-docs/layouts/includes/sidebar.html.erb +31 -0
- data/lib/json-schema-docs/layouts/links.html.erb +73 -0
- data/lib/json-schema-docs/layouts/resource.html.erb +42 -0
- data/lib/json-schema-docs/parser.rb +12 -6
- data/lib/json-schema-docs/renderer.rb +67 -0
- data/lib/json-schema-docs/version.rb +1 -1
- metadata +144 -6
- data/lib/json-schema-docs/layouts/endpoint.md.erb +0 -39
- data/lib/json-schema-docs/layouts/object.md.erb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 70ce09af68c836c67047b91049579f0907fe9e4e8b935211482dd6163bb96bc2
|
4
|
+
data.tar.gz: a069ce9a8503d02bcf5d98f608ad734f335296b25a8528701b26a0eb4306a286
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f4ff3f550c966a17f8faf158564610b14132e044a3aafcc0c1614f4509a961ef77ad03e0967e6d8a73a3942c1ac23c97e89904ed473ec4799117510cff93e31c
|
7
|
+
data.tar.gz: 48e657b95352ef05360e07137fea1748deaa4cdcbe6d87bbb9c3f6f6c71f5c0523afd1d64ee85dfcfcbe313c5fb558e9478f6450f1c724879c22fa87e96a2075
|
data/README.md
CHANGED
@@ -39,7 +39,8 @@ There are several phases going on the single `JsonSchemaDocs.build` call:
|
|
39
39
|
|
40
40
|
* The JSON schema file is read (if you passed `filename`) through `Prmd::Schema` (or simply consumed if you passed it through `schema`).
|
41
41
|
* `JsonSchemaDocs::Parser` manipulates the schema into a slightly saner format.
|
42
|
-
* `JsonSchemaDocs::Generator` takes that saner format and
|
42
|
+
* `JsonSchemaDocs::Generator` takes that saner format and begins the process of applying items to the HTML templates.
|
43
|
+
* `JsonSchemaDocs::Renderer` technically runs as part of the generation phase. It passes the contents of each page and converts it into HTML.
|
43
44
|
|
44
45
|
If you wanted to, you could break these calls up individually. For example:
|
45
46
|
|
@@ -47,7 +48,7 @@ If you wanted to, you could break these calls up individually. For example:
|
|
47
48
|
options = {}
|
48
49
|
options[:filename] = "#{File.dirname(__FILE__)}/../data/schema.json"
|
49
50
|
|
50
|
-
options = JsonSchemaDocs::Configuration::
|
51
|
+
options = JsonSchemaDocs::Configuration::JSON_SCHEMA_DOCS_DEFAULTS.merge(options)
|
51
52
|
|
52
53
|
response = File.read(options[:filename])
|
53
54
|
|
@@ -61,14 +62,47 @@ generator.generate
|
|
61
62
|
|
62
63
|
## Generating output
|
63
64
|
|
64
|
-
By default, the generation process uses ERB to layout the content
|
65
|
+
By default, the generation process uses ERB to layout the content. There are a bunch of default options provided for you, but feel free to override any of these. The *Configuration* section below has more information on what you can change.
|
66
|
+
|
67
|
+
It also uses [html-pipeline](https://github.com/jch/html-pipeline) to perform the rendering by default. You can override this by providing a custom rendering class.You must implement two methods:
|
68
|
+
|
69
|
+
* `initialize` - Takes two arguments, the parsed `schema` and the configuration `options`.
|
70
|
+
* `render` Takes the contents of a template page. It also takes an optional kwargs, `meta`, for anything you want to include in your template. For example:
|
71
|
+
|
72
|
+
``` ruby
|
73
|
+
class CustomRenderer
|
74
|
+
def initialize(parsed_schema, options)
|
75
|
+
@parsed_schema = parsed_schema
|
76
|
+
@options = options
|
77
|
+
end
|
78
|
+
|
79
|
+
def render(contents, meta: {})
|
80
|
+
contents = contents.sub(/Repository/i, '<strong>Meow Woof!</strong>')
|
81
|
+
opts = meta.merge({ foo: "bar" })
|
82
|
+
|
83
|
+
@default_layout.result(OpenStruct.new(opts).instance_eval { binding })
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
options[:filename] = 'location/to/schema.json'
|
88
|
+
options[:renderer] = CustomRenderer
|
89
|
+
|
90
|
+
JsonSchemaDocs.build(options)
|
91
|
+
```
|
92
|
+
|
93
|
+
If your `render` method returns `nil`, the `Generator` will not attempt to write any HTML file.
|
65
94
|
|
66
95
|
### Helper methods
|
67
96
|
|
68
97
|
In your ERB layouts, there are several helper methods you can use. The helper methods are:
|
69
98
|
|
70
|
-
* `slugify(str)
|
71
|
-
* `include(filename, opts)
|
99
|
+
* `slugify(str)`: This slugifies the given string.
|
100
|
+
* `include(filename, opts)`: This embeds a template from your `includes` folder, passing along the local options provided.
|
101
|
+
* `markdownify(string)`: This converts a string into HTML via CommonMarker.
|
102
|
+
* `types`: Collections of the various types.
|
103
|
+
* `schemata(name)`: The schemata defined by `name`.
|
104
|
+
|
105
|
+
To call these methods within templates, you must use the dot notation, such as `<%= slugify.(text) %>`.
|
72
106
|
|
73
107
|
## Configuration
|
74
108
|
|
@@ -76,11 +110,16 @@ The following options are available:
|
|
76
110
|
|
77
111
|
| Option | Description | Default |
|
78
112
|
| :----- | :---------- | :------ |
|
79
|
-
| `filename` | The location of your schema's
|
80
|
-
| `schema` | A string representing a schema
|
113
|
+
| `filename` | The location of your schema's JSON file. | `nil` |
|
114
|
+
| `schema` | A string representing a schema JSON file. | `nil` |
|
115
|
+
| `output_dir` | The location of the output HTML files. | `./output/` |
|
116
|
+
| `use_default_styles` | Indicates if you want to use the default styles. | `true` |
|
117
|
+
| `base_url` | Indicates the base URL to prepend for assets and links. | `""` |
|
81
118
|
| `delete_output` | Deletes `output_dir` before generating content. | `false` |
|
82
|
-
| `
|
83
|
-
| `
|
119
|
+
| `pipeline_config` | Defines two sub-keys, `pipeline` and `context`, which are used by `html-pipeline` when rendering your output. | The defaults are found in _lib/json-schema-docs/configuration.rb/_ |
|
120
|
+
| `renderer` | The rendering class to use. | `JsonSchemaDocs::Renderer`
|
121
|
+
| `templates` | The templates to use when generating HTML. You may override any of the following keys: `default`, `links`, `resource`. | The defaults are found in _lib/json-schema-docs/layouts/_.
|
122
|
+
| `landing_pages` | The landing page to use when generating HTML for each type. You may override any of the following keys: `index`. | The defaults are found in _lib/json-schema-docs/landing\_pages/_.
|
84
123
|
| `prmd` | The options to pass into PRMD's parser. | The defaults are found in _lib/json-schema-docs/configuration.rb/_.
|
85
124
|
|
86
125
|
## Development
|
data/Rakefile
CHANGED
@@ -33,14 +33,7 @@ task sample: [:generate_sample] do
|
|
33
33
|
|
34
34
|
puts 'Navigate to http://localhost:3000 to see the sample docs'
|
35
35
|
|
36
|
-
|
37
|
-
mime_types.store 'md', 'text/plain'
|
38
|
-
|
39
|
-
options = {
|
40
|
-
Port: 3000,
|
41
|
-
MimeTypes: mime_types
|
42
|
-
}
|
43
|
-
server = WEBrick::HTTPServer.new options
|
36
|
+
server = WEBrick::HTTPServer.new Port: 3000
|
44
37
|
server.mount '/', WEBrick::HTTPServlet::FileHandler, 'output'
|
45
38
|
trap('INT') { server.stop }
|
46
39
|
server.start
|
data/json-schema-docs.gemspec
CHANGED
@@ -23,6 +23,17 @@ Gem::Specification.new do |spec|
|
|
23
23
|
|
24
24
|
spec.add_dependency 'prmd', '~> 0.13'
|
25
25
|
|
26
|
+
# rendering
|
27
|
+
spec.add_dependency 'commonmarker', '~> 0.16'
|
28
|
+
spec.add_dependency 'gemoji', '~> 3.0'
|
29
|
+
spec.add_dependency 'html-pipeline', '~> 2.9'
|
30
|
+
spec.add_dependency 'escape_utils', '~> 1.2'
|
31
|
+
spec.add_dependency 'extended-markdown-filter', '~> 0.4'
|
32
|
+
spec.add_dependency 'neatjson', '~> 0.9'
|
33
|
+
spec.add_dependency 'page-toc-filter', '~> 0.2'
|
34
|
+
spec.add_dependency 'rouge', '~> 3.10'
|
35
|
+
spec.add_dependency 'sass', '~> 3.4'
|
36
|
+
|
26
37
|
spec.add_development_dependency 'awesome_print'
|
27
38
|
spec.add_development_dependency 'html-proofer', '~> 3.4'
|
28
39
|
spec.add_development_dependency 'minitest', '~> 5.0'
|
data/lib/json-schema-docs.rb
CHANGED
@@ -9,12 +9,35 @@ module JsonSchemaDocs
|
|
9
9
|
# Generating
|
10
10
|
delete_output: false,
|
11
11
|
output_dir: './output/',
|
12
|
+
pipeline_config: {
|
13
|
+
pipeline:
|
14
|
+
%i(ExtendedMarkdownFilter
|
15
|
+
EmojiFilter
|
16
|
+
TableOfContentsFilter
|
17
|
+
SyntaxHighlightFilter),
|
18
|
+
context: {
|
19
|
+
gfm: false,
|
20
|
+
unsafe: true, # necessary for layout needs, given that it's all HTML templates
|
21
|
+
asset_root: 'https://a248.e.akamai.net/assets.github.com/images/icons'
|
22
|
+
}
|
23
|
+
},
|
24
|
+
renderer: JsonSchemaDocs::Renderer,
|
25
|
+
use_default_styles: true,
|
26
|
+
base_url: '',
|
12
27
|
|
13
28
|
templates: {
|
14
|
-
|
15
|
-
object: "#{File.dirname(__FILE__)}/layouts/object.md.erb",
|
29
|
+
default: "#{File.dirname(__FILE__)}/layouts/default.html.erb",
|
16
30
|
|
17
31
|
includes: "#{File.dirname(__FILE__)}/layouts/includes",
|
32
|
+
|
33
|
+
links: "#{File.dirname(__FILE__)}/layouts/links.html.erb",
|
34
|
+
resource: "#{File.dirname(__FILE__)}/layouts/resource.html.erb",
|
35
|
+
},
|
36
|
+
|
37
|
+
landing_pages: {
|
38
|
+
index: "#{File.dirname(__FILE__)}/landing_pages/index.md",
|
39
|
+
|
40
|
+
variables: {} # only used for ERB landing pages
|
18
41
|
},
|
19
42
|
|
20
43
|
prmd: {
|
@@ -7,50 +7,92 @@ module JsonSchemaDocs
|
|
7
7
|
|
8
8
|
attr_accessor :parsed_schema
|
9
9
|
|
10
|
+
DYNAMIC_PAGES = %i(links resource)
|
11
|
+
STATIC_PAGES = %i(index)
|
12
|
+
|
10
13
|
def initialize(parsed_schema, options)
|
11
14
|
@parsed_schema = parsed_schema
|
12
15
|
@options = options
|
13
16
|
|
14
|
-
|
17
|
+
@renderer = @options[:renderer].new(@parsed_schema, @options)
|
18
|
+
|
19
|
+
DYNAMIC_PAGES.each do |sym|
|
15
20
|
if !File.exist?(@options[:templates][sym])
|
16
21
|
raise IOError, "`#{sym}` template #{@options[:templates][sym]} was not found"
|
17
22
|
end
|
18
23
|
instance_variable_set("@json_schema_#{sym}_template", ERB.new(File.read(@options[:templates][sym]), nil, '-'))
|
19
24
|
end
|
25
|
+
|
26
|
+
STATIC_PAGES.each do |sym|
|
27
|
+
if @options[:landing_pages][sym].nil?
|
28
|
+
instance_variable_set("@#{sym}_landing_page", nil)
|
29
|
+
elsif !File.exist?(@options[:landing_pages][sym])
|
30
|
+
raise IOError, "`#{sym}` landing page #{@options[:landing_pages][sym]} was not found"
|
31
|
+
end
|
32
|
+
|
33
|
+
landing_page_contents = File.read(@options[:landing_pages][sym])
|
34
|
+
|
35
|
+
instance_variable_set("@json_schema_#{sym}_landing_page", landing_page_contents)
|
36
|
+
end
|
20
37
|
end
|
21
38
|
|
22
39
|
def generate
|
23
40
|
FileUtils.rm_rf(@options[:output_dir]) if @options[:delete_output]
|
24
41
|
|
25
42
|
@parsed_schema.each_pair do |resource, schemata|
|
26
|
-
|
27
|
-
|
28
|
-
|
43
|
+
DYNAMIC_PAGES.each do |type|
|
44
|
+
layout = instance_variable_get("@json_schema_#{type}_template")
|
45
|
+
opts = @options.merge(helper_methods)
|
29
46
|
|
30
|
-
|
47
|
+
opts[:schemata_resource] = resource
|
48
|
+
opts[:schemata] = schemata
|
49
|
+
|
50
|
+
contents = layout.result(OpenStruct.new(opts).instance_eval { binding })
|
31
51
|
write_file(type, resource, contents)
|
32
52
|
end
|
33
53
|
end
|
34
|
-
end
|
35
54
|
|
36
|
-
|
55
|
+
STATIC_PAGES.each do |name|
|
56
|
+
landing_page = instance_variable_get("@json_schema_#{name}_landing_page")
|
57
|
+
|
58
|
+
unless landing_page.nil?
|
59
|
+
write_file(:landing_page, name.to_s, landing_page, trim: false)
|
60
|
+
end
|
61
|
+
end
|
37
62
|
|
38
|
-
|
39
|
-
|
40
|
-
|
63
|
+
if @options[:use_default_styles]
|
64
|
+
assets_dir = File.join(File.dirname(__FILE__), 'layouts', 'assets')
|
65
|
+
FileUtils.mkdir_p(File.join(@options[:output_dir], 'assets'))
|
66
|
+
|
67
|
+
sass = File.join(assets_dir, 'css', 'screen.scss')
|
68
|
+
system `sass --sourcemap=none #{sass}:#{@options[:output_dir]}/assets/style.css`
|
69
|
+
end
|
41
70
|
|
42
|
-
|
43
|
-
opts[:schemata] = schemata
|
44
|
-
layout.result(OpenStruct.new(opts).instance_eval { binding })
|
71
|
+
true
|
45
72
|
end
|
46
73
|
|
74
|
+
private
|
75
|
+
|
47
76
|
def write_file(type, name, contents, trim: true)
|
48
|
-
if type == :
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
77
|
+
if type == :landing_page
|
78
|
+
if name == 'index'
|
79
|
+
path = @options[:output_dir]
|
80
|
+
else
|
81
|
+
path = File.join(@options[:output_dir], name)
|
82
|
+
FileUtils.mkdir_p(path)
|
83
|
+
end
|
84
|
+
elsif type == :resource
|
85
|
+
path = File.join(@options[:output_dir], 'resources', name.downcase)
|
86
|
+
elsif type == :links
|
87
|
+
path = File.join(@options[:output_dir], 'resources', name.downcase, 'links')
|
88
|
+
end
|
89
|
+
|
90
|
+
FileUtils.mkdir_p(path)
|
91
|
+
|
92
|
+
meta = { title: name, name: name }
|
93
|
+
if has_yaml?(contents)
|
94
|
+
# Split data
|
95
|
+
meta, contents = split_into_metadata_and_contents(contents)
|
54
96
|
end
|
55
97
|
|
56
98
|
if trim
|
@@ -59,8 +101,38 @@ module JsonSchemaDocs
|
|
59
101
|
contents = contents.gsub(/^\s{4}/m, ' ')
|
60
102
|
end
|
61
103
|
|
62
|
-
filename = File.join(path, 'index.
|
63
|
-
|
104
|
+
filename = File.join(path, 'index.html')
|
105
|
+
output = @renderer.render(contents, meta: meta)
|
106
|
+
File.write(filename, output) unless output.nil?
|
107
|
+
end
|
108
|
+
|
109
|
+
def split_into_metadata_and_contents(contents, parse: true)
|
110
|
+
opts = {}
|
111
|
+
pieces = yaml_split(contents)
|
112
|
+
if pieces.size < 4
|
113
|
+
raise RuntimeError.new(
|
114
|
+
"The file '#{content_filename}' appears to start with a metadata section (three or five dashes at the top) but it does not seem to be in the correct format.",
|
115
|
+
)
|
116
|
+
end
|
117
|
+
# Parse
|
118
|
+
begin
|
119
|
+
if parse
|
120
|
+
meta = YAML.load(pieces[2]) || {}
|
121
|
+
else
|
122
|
+
meta = pieces[2]
|
123
|
+
end
|
124
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
125
|
+
raise "Could not parse YAML for #{name}: #{e.message}"
|
126
|
+
end
|
127
|
+
[meta, pieces[4]]
|
128
|
+
end
|
129
|
+
|
130
|
+
def has_yaml?(contents)
|
131
|
+
contents =~ /\A-{3,5}\s*$/
|
132
|
+
end
|
133
|
+
|
134
|
+
def yaml_split(contents)
|
135
|
+
contents.split(/^(-{5}|-{3})[ \t]*\r?\n?/, 3)
|
64
136
|
end
|
65
137
|
end
|
66
138
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'commonmarker'
|
4
|
+
|
3
5
|
module JsonSchemaDocs
|
4
6
|
module Helpers
|
5
7
|
SLUGIFY_PRETTY_REGEXP = Regexp.new("[^[:alnum:]._~!$&'()+,;=@]+").freeze
|
@@ -14,10 +16,24 @@ module JsonSchemaDocs
|
|
14
16
|
|
15
17
|
def include(filename, opts = {})
|
16
18
|
template = fetch_include(filename)
|
17
|
-
opts = @options.merge(opts)
|
19
|
+
opts = { base_url: @options[:base_url] }.merge(opts)
|
18
20
|
template.result(OpenStruct.new(opts.merge(helper_methods)).instance_eval { binding })
|
19
21
|
end
|
20
22
|
|
23
|
+
def markdownify(string)
|
24
|
+
return '' if string.nil?
|
25
|
+
type = @options[:pipeline_config][:context][:unsafe] ? :UNSAFE : :DEFAULT
|
26
|
+
::CommonMarker.render_html(string, type).strip
|
27
|
+
end
|
28
|
+
|
29
|
+
def types
|
30
|
+
@parsed_schema.keys
|
31
|
+
end
|
32
|
+
|
33
|
+
def schemata(name)
|
34
|
+
@parsed_schema[name]
|
35
|
+
end
|
36
|
+
|
21
37
|
private
|
22
38
|
|
23
39
|
def fetch_include(filename)
|
@@ -0,0 +1,518 @@
|
|
1
|
+
#content {
|
2
|
+
padding: 20px 30px;
|
3
|
+
margin: 0px auto;
|
4
|
+
-webkit-text-size-adjust: 100%;
|
5
|
+
em {
|
6
|
+
font-style: italic;
|
7
|
+
}
|
8
|
+
strong {
|
9
|
+
font-family: "ProximaNova-Bold";
|
10
|
+
}
|
11
|
+
h1 {
|
12
|
+
margin: 15px 0;
|
13
|
+
line-height: 1.4em;
|
14
|
+
font-size: 2em;
|
15
|
+
margin-top: 0;
|
16
|
+
margin-bottom: 30px;
|
17
|
+
}
|
18
|
+
h2 {
|
19
|
+
margin: 15px 0;
|
20
|
+
line-height: 1.4em;
|
21
|
+
font-size: 1.5em;
|
22
|
+
margin-top: 30px;
|
23
|
+
padding-bottom: 10px;
|
24
|
+
border-bottom: 1px solid #eee;
|
25
|
+
position: relative;
|
26
|
+
.anchor {
|
27
|
+
opacity: 0;
|
28
|
+
position: absolute;
|
29
|
+
font-size: 16px;
|
30
|
+
top: 2px;
|
31
|
+
left: -21px;
|
32
|
+
}
|
33
|
+
&:hover {
|
34
|
+
.anchor {
|
35
|
+
opacity: 1;
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
39
|
+
h3 {
|
40
|
+
margin: 15px 0;
|
41
|
+
line-height: 1.4em;
|
42
|
+
font-size: 1.2em;
|
43
|
+
margin-top: 30px;
|
44
|
+
position: relative;
|
45
|
+
.anchor {
|
46
|
+
opacity: 0;
|
47
|
+
position: absolute;
|
48
|
+
font-size: 16px;
|
49
|
+
top: 2px;
|
50
|
+
left: -21px;
|
51
|
+
}
|
52
|
+
&:hover {
|
53
|
+
.anchor {
|
54
|
+
opacity: 1;
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
h4 {
|
59
|
+
margin: 15px 0;
|
60
|
+
line-height: 1.4em;
|
61
|
+
}
|
62
|
+
h5 {
|
63
|
+
margin: 15px 0;
|
64
|
+
line-height: 1.4em;
|
65
|
+
}
|
66
|
+
h6 {
|
67
|
+
margin: 15px 0;
|
68
|
+
line-height: 1.4em;
|
69
|
+
}
|
70
|
+
p {
|
71
|
+
margin: 15px 0;
|
72
|
+
line-height: 1.4em;
|
73
|
+
}
|
74
|
+
ul {
|
75
|
+
margin: 15px 0;
|
76
|
+
line-height: 1.4em;
|
77
|
+
padding-left: 1.5em;
|
78
|
+
list-style-type: disc;
|
79
|
+
li {
|
80
|
+
margin-bottom: 5px;
|
81
|
+
}
|
82
|
+
}
|
83
|
+
ol {
|
84
|
+
margin: 15px 0;
|
85
|
+
line-height: 1.4em;
|
86
|
+
padding-left: 1.5em;
|
87
|
+
list-style-type: decimal;
|
88
|
+
li {
|
89
|
+
margin-bottom: 5px;
|
90
|
+
}
|
91
|
+
}
|
92
|
+
figure {
|
93
|
+
margin: 15px 0;
|
94
|
+
line-height: 1.4em;
|
95
|
+
}
|
96
|
+
a {
|
97
|
+
color: #de4f4f;
|
98
|
+
}
|
99
|
+
img {
|
100
|
+
max-width: 100%;
|
101
|
+
}
|
102
|
+
code {
|
103
|
+
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
|
104
|
+
font-size: 0.8em;
|
105
|
+
line-height: 1.6em;
|
106
|
+
padding: 1px 4px;
|
107
|
+
background-color: #eee;
|
108
|
+
margin: 0 2px;
|
109
|
+
}
|
110
|
+
blockquote {
|
111
|
+
padding-left: 1.3em;
|
112
|
+
border-left: #eee solid 0.2em;
|
113
|
+
font-style: italic;
|
114
|
+
}
|
115
|
+
blockquote.warning {
|
116
|
+
border-color: #f00;
|
117
|
+
color: #f00;
|
118
|
+
}
|
119
|
+
dl {
|
120
|
+
margin-left: 1.5em;
|
121
|
+
dt {
|
122
|
+
.name {
|
123
|
+
font-family: monospace;
|
124
|
+
}
|
125
|
+
.type {
|
126
|
+
margin-left: 0.5em;
|
127
|
+
}
|
128
|
+
}
|
129
|
+
dd {
|
130
|
+
margin-left: 1.5em;
|
131
|
+
}
|
132
|
+
}
|
133
|
+
.edit-discuss-links {
|
134
|
+
margin-top: -25px;
|
135
|
+
margin-bottom: 40px;
|
136
|
+
}
|
137
|
+
table {
|
138
|
+
margin-top: 10px;
|
139
|
+
th {
|
140
|
+
text-align: left;
|
141
|
+
padding: 0 25px 0 25px;
|
142
|
+
}
|
143
|
+
thead th:first-child {
|
144
|
+
padding: 0;
|
145
|
+
}
|
146
|
+
td p {
|
147
|
+
padding: 0 25px 0 25px;
|
148
|
+
}
|
149
|
+
}
|
150
|
+
pre {
|
151
|
+
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
|
152
|
+
line-height: 1.6em;
|
153
|
+
margin: 20px 0;
|
154
|
+
overflow-x: auto;
|
155
|
+
position: relative;
|
156
|
+
padding: 20px 30px;
|
157
|
+
table {
|
158
|
+
width: 100%;
|
159
|
+
border-collapse: collapse;
|
160
|
+
padding: 0;
|
161
|
+
margin: 0;
|
162
|
+
}
|
163
|
+
tr {
|
164
|
+
width: 100%;
|
165
|
+
border-collapse: collapse;
|
166
|
+
padding: 0;
|
167
|
+
margin: 0;
|
168
|
+
}
|
169
|
+
td {
|
170
|
+
width: 100%;
|
171
|
+
border-collapse: collapse;
|
172
|
+
padding: 0;
|
173
|
+
margin: 0;
|
174
|
+
}
|
175
|
+
code {
|
176
|
+
background-color: #272822;
|
177
|
+
padding: 0;
|
178
|
+
margin: 0;
|
179
|
+
}
|
180
|
+
.gutter {
|
181
|
+
user-select: none;
|
182
|
+
width: 1.5em;
|
183
|
+
padding-right: 30px;
|
184
|
+
}
|
185
|
+
}
|
186
|
+
.highlight.html {
|
187
|
+
.code {
|
188
|
+
&:after {
|
189
|
+
font-family: "ProximaNova-Semibold";
|
190
|
+
position: absolute;
|
191
|
+
top: 0;
|
192
|
+
right: 0;
|
193
|
+
color: #ccc;
|
194
|
+
text-align: right;
|
195
|
+
font-size: 0.75em;
|
196
|
+
padding: 5px 10px 0;
|
197
|
+
letter-spacing: 1.5px;
|
198
|
+
line-height: 15px;
|
199
|
+
height: 15px;
|
200
|
+
font-weight: 600;
|
201
|
+
}
|
202
|
+
}
|
203
|
+
}
|
204
|
+
.highlight.js {
|
205
|
+
.code {
|
206
|
+
&:after {
|
207
|
+
font-family: "ProximaNova-Semibold";
|
208
|
+
position: absolute;
|
209
|
+
top: 0;
|
210
|
+
right: 0;
|
211
|
+
color: #ccc;
|
212
|
+
text-align: right;
|
213
|
+
font-size: 0.75em;
|
214
|
+
padding: 5px 10px 0;
|
215
|
+
letter-spacing: 1.5px;
|
216
|
+
line-height: 15px;
|
217
|
+
height: 15px;
|
218
|
+
font-weight: 600;
|
219
|
+
}
|
220
|
+
}
|
221
|
+
}
|
222
|
+
.highlight.bash {
|
223
|
+
.code {
|
224
|
+
&:after {
|
225
|
+
font-family: "ProximaNova-Semibold";
|
226
|
+
position: absolute;
|
227
|
+
top: 0;
|
228
|
+
right: 0;
|
229
|
+
color: #ccc;
|
230
|
+
text-align: right;
|
231
|
+
font-size: 0.75em;
|
232
|
+
padding: 5px 10px 0;
|
233
|
+
letter-spacing: 1.5px;
|
234
|
+
line-height: 15px;
|
235
|
+
height: 15px;
|
236
|
+
font-weight: 600;
|
237
|
+
}
|
238
|
+
}
|
239
|
+
}
|
240
|
+
.highlight.css {
|
241
|
+
.code {
|
242
|
+
&:after {
|
243
|
+
font-family: "ProximaNova-Semibold";
|
244
|
+
position: absolute;
|
245
|
+
top: 0;
|
246
|
+
right: 0;
|
247
|
+
color: #ccc;
|
248
|
+
text-align: right;
|
249
|
+
font-size: 0.75em;
|
250
|
+
padding: 5px 10px 0;
|
251
|
+
letter-spacing: 1.5px;
|
252
|
+
line-height: 15px;
|
253
|
+
height: 15px;
|
254
|
+
font-weight: 600;
|
255
|
+
}
|
256
|
+
}
|
257
|
+
}
|
258
|
+
.highlight.jsx {
|
259
|
+
.code {
|
260
|
+
&:after {
|
261
|
+
font-family: "ProximaNova-Semibold";
|
262
|
+
position: absolute;
|
263
|
+
top: 0;
|
264
|
+
right: 0;
|
265
|
+
color: #ccc;
|
266
|
+
text-align: right;
|
267
|
+
font-size: 0.75em;
|
268
|
+
padding: 5px 10px 0;
|
269
|
+
letter-spacing: 1.5px;
|
270
|
+
line-height: 15px;
|
271
|
+
height: 15px;
|
272
|
+
font-weight: 600;
|
273
|
+
}
|
274
|
+
}
|
275
|
+
}
|
276
|
+
.highlight.html.html {
|
277
|
+
.code {
|
278
|
+
&:after {
|
279
|
+
content: "HTML";
|
280
|
+
}
|
281
|
+
}
|
282
|
+
}
|
283
|
+
.highlight.js.html {
|
284
|
+
.code {
|
285
|
+
&:after {
|
286
|
+
content: "HTML";
|
287
|
+
}
|
288
|
+
}
|
289
|
+
}
|
290
|
+
.highlight.bash.html {
|
291
|
+
.code {
|
292
|
+
&:after {
|
293
|
+
content: "HTML";
|
294
|
+
}
|
295
|
+
}
|
296
|
+
}
|
297
|
+
.highlight.css.html {
|
298
|
+
.code {
|
299
|
+
&:after {
|
300
|
+
content: "HTML";
|
301
|
+
}
|
302
|
+
}
|
303
|
+
}
|
304
|
+
.highlight.jsx.html {
|
305
|
+
.code {
|
306
|
+
&:after {
|
307
|
+
content: "HTML";
|
308
|
+
}
|
309
|
+
}
|
310
|
+
}
|
311
|
+
.highlight.html.js {
|
312
|
+
.code {
|
313
|
+
&:after {
|
314
|
+
content: "JS";
|
315
|
+
}
|
316
|
+
}
|
317
|
+
}
|
318
|
+
.highlight.js.js {
|
319
|
+
.code {
|
320
|
+
&:after {
|
321
|
+
content: "JS";
|
322
|
+
}
|
323
|
+
}
|
324
|
+
}
|
325
|
+
.highlight.bash.js {
|
326
|
+
.code {
|
327
|
+
&:after {
|
328
|
+
content: "JS";
|
329
|
+
}
|
330
|
+
}
|
331
|
+
}
|
332
|
+
.highlight.css.js {
|
333
|
+
.code {
|
334
|
+
&:after {
|
335
|
+
content: "JS";
|
336
|
+
}
|
337
|
+
}
|
338
|
+
}
|
339
|
+
.highlight.jsx.js {
|
340
|
+
.code {
|
341
|
+
&:after {
|
342
|
+
content: "JS";
|
343
|
+
}
|
344
|
+
}
|
345
|
+
}
|
346
|
+
.highlight.html.bash {
|
347
|
+
.code {
|
348
|
+
&:after {
|
349
|
+
content: "Shell";
|
350
|
+
}
|
351
|
+
}
|
352
|
+
}
|
353
|
+
.highlight.js.bash {
|
354
|
+
.code {
|
355
|
+
&:after {
|
356
|
+
content: "Shell";
|
357
|
+
}
|
358
|
+
}
|
359
|
+
}
|
360
|
+
.highlight.bash.bash {
|
361
|
+
.code {
|
362
|
+
&:after {
|
363
|
+
content: "Shell";
|
364
|
+
}
|
365
|
+
}
|
366
|
+
}
|
367
|
+
.highlight.css.bash {
|
368
|
+
.code {
|
369
|
+
&:after {
|
370
|
+
content: "Shell";
|
371
|
+
}
|
372
|
+
}
|
373
|
+
}
|
374
|
+
.highlight.jsx.bash {
|
375
|
+
.code {
|
376
|
+
&:after {
|
377
|
+
content: "Shell";
|
378
|
+
}
|
379
|
+
}
|
380
|
+
}
|
381
|
+
.highlight.html.css {
|
382
|
+
.code {
|
383
|
+
&:after {
|
384
|
+
content: "CSS";
|
385
|
+
}
|
386
|
+
}
|
387
|
+
}
|
388
|
+
.highlight.js.css {
|
389
|
+
.code {
|
390
|
+
&:after {
|
391
|
+
content: "CSS";
|
392
|
+
}
|
393
|
+
}
|
394
|
+
}
|
395
|
+
.highlight.bash.css {
|
396
|
+
.code {
|
397
|
+
&:after {
|
398
|
+
content: "CSS";
|
399
|
+
}
|
400
|
+
}
|
401
|
+
}
|
402
|
+
.highlight.css.css {
|
403
|
+
.code {
|
404
|
+
&:after {
|
405
|
+
content: "CSS";
|
406
|
+
}
|
407
|
+
}
|
408
|
+
}
|
409
|
+
.highlight.jsx.css {
|
410
|
+
.code {
|
411
|
+
&:after {
|
412
|
+
content: "CSS";
|
413
|
+
}
|
414
|
+
}
|
415
|
+
}
|
416
|
+
.highlight.html.jsx {
|
417
|
+
.code {
|
418
|
+
&:after {
|
419
|
+
content: "JSX";
|
420
|
+
}
|
421
|
+
}
|
422
|
+
}
|
423
|
+
.highlight.js.jsx {
|
424
|
+
.code {
|
425
|
+
&:after {
|
426
|
+
content: "JSX";
|
427
|
+
}
|
428
|
+
}
|
429
|
+
}
|
430
|
+
.highlight.bash.jsx {
|
431
|
+
.code {
|
432
|
+
&:after {
|
433
|
+
content: "JSX";
|
434
|
+
}
|
435
|
+
}
|
436
|
+
}
|
437
|
+
.highlight.css.jsx {
|
438
|
+
.code {
|
439
|
+
&:after {
|
440
|
+
content: "JSX";
|
441
|
+
}
|
442
|
+
}
|
443
|
+
}
|
444
|
+
.highlight.jsx.jsx {
|
445
|
+
.code {
|
446
|
+
&:after {
|
447
|
+
content: "JSX";
|
448
|
+
}
|
449
|
+
}
|
450
|
+
}
|
451
|
+
> table {
|
452
|
+
width: 100%;
|
453
|
+
margin: 20px 0;
|
454
|
+
tr {
|
455
|
+
border-top: 1px solid #eee;
|
456
|
+
&:nth-child(2n) {
|
457
|
+
background-color: #f8f8f8;
|
458
|
+
}
|
459
|
+
}
|
460
|
+
th {
|
461
|
+
font-family: "ProximaNova-Semibold";
|
462
|
+
padding: 12px 13px;
|
463
|
+
border: 1px solid #eee;
|
464
|
+
vertical-align: middle;
|
465
|
+
text-align: left;
|
466
|
+
}
|
467
|
+
td {
|
468
|
+
border: 1px solid #eee;
|
469
|
+
vertical-align: middle;
|
470
|
+
padding: 6px 13px;
|
471
|
+
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
|
472
|
+
font-size: 0.8em;
|
473
|
+
line-height: 1.6em;
|
474
|
+
}
|
475
|
+
}
|
476
|
+
.bottom-nav {
|
477
|
+
height: 44px;
|
478
|
+
margin: 30px 0 25px;
|
479
|
+
border-bottom: 1px solid #eee;
|
480
|
+
padding-bottom: 25px;
|
481
|
+
a {
|
482
|
+
font-family: "ProximaNova-Semibold";
|
483
|
+
margin: 0 5px;
|
484
|
+
}
|
485
|
+
}
|
486
|
+
.edit-link {
|
487
|
+
text-align: center;
|
488
|
+
a {
|
489
|
+
color: #aaa;
|
490
|
+
font-family: "ProximaNova-Semibold";
|
491
|
+
&:before {
|
492
|
+
content: "";
|
493
|
+
display: inline-block;
|
494
|
+
width: 16px;
|
495
|
+
height: 16px;
|
496
|
+
background-size: 16px;
|
497
|
+
opacity: 0.3;
|
498
|
+
margin-right: 8px;
|
499
|
+
position: relative;
|
500
|
+
top: 2px;
|
501
|
+
}
|
502
|
+
}
|
503
|
+
}
|
504
|
+
|
505
|
+
.field-name {
|
506
|
+
font-weight: bold;
|
507
|
+
}
|
508
|
+
|
509
|
+
.field-entry {
|
510
|
+
margin-bottom: 4rem;
|
511
|
+
}
|
512
|
+
.description-wrapper {
|
513
|
+
> p {
|
514
|
+
padding-left: 1rem;
|
515
|
+
margin-bottom: 1rem;
|
516
|
+
}
|
517
|
+
}
|
518
|
+
}
|