asciidoctor-diagram-layout 1.0.1 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 259d60e19f11c5464595f92d72139d65650d5c9323a1be52604e576ebc07fa00
4
- data.tar.gz: 3943431e97a920a3793802bd2749d74912f96eb6d9c8292e99d708345599ece5
3
+ metadata.gz: c49ff65f5b48299da96077abff591082253d7d235f7d04c376563722b6ef3fdd
4
+ data.tar.gz: 120ad77f8019c03234c9c58e7dfc10fbd6332baebb81f2ba58a83268f3a34d21
5
5
  SHA512:
6
- metadata.gz: 8f02690b155ef916aab876e901ea19f3d3a987531057c28f45a8a448caa350e10420ce390a1374daf45d390edb52af3443f814469eabc219a446b51f9276d1b0
7
- data.tar.gz: b9df257e16623a6107627bc55b7a4f086f276582f6abb3acecfdea0708fc581010423a3448bcdc3861abe89c03bdabe7b27be65b607bf4dab4afaddabcfd92de
6
+ metadata.gz: 643df3c7a743cd9f67b7c067c9e19cb251de1e4b2bc3cbdf6457985f7ced4aab41612214d084b050218562b016ffd425346b5e1c705f575cc65233962ac20847
7
+ data.tar.gz: 874427307fe73724a2d47b0f2010280585f10c209348366ffce5d95c5809441f0e195808c7c6a967ff8e2d519e97a0b6bd20ddffc4961a629efec9b2e16df971
data/README.md CHANGED
@@ -1,7 +1,27 @@
1
1
  # asciidoctor-diagram-layout
2
2
 
3
- An Asciidoctor extension that adds a `[layout-rowcol]` block for
4
- rendering flex-based layout diagrams as HTML or SVG.
3
+ An Asciidoctor extension for documenting UI layouts as diagrams,
4
+ intended for describing the structure of composite views (pages, screens,
5
+ etc.).
6
+
7
+ ## The problem
8
+
9
+ When writing software requirements or design documents, you often need
10
+ to describe the layout of a screen or a page: which areas exist, how
11
+ they are positioned relative to each other, and what proportion of
12
+ space each one occupies.
13
+
14
+ The usual alternatives are screenshots, wireframe tools, or hand-drawn
15
+ sketches - none of which live well next to the text, can be diffed in
16
+ version control, or stay in sync as the design evolves.
17
+
18
+ This extension lets you describe a layout directly in AsciiDoc source
19
+ using a simple line-oriented DSL.
20
+ The same source serves as both a human-readable description of the
21
+ structure and a machine-rendered visual diagram - there is no separate
22
+ "source" and "picture" to keep in sync.
23
+ The diagram is rendered as HTML (for web output) or SVG (for PDF and
24
+ other backends) without any external tools.
5
25
 
6
26
  ## Installation
7
27
 
@@ -19,71 +39,229 @@ gem install asciidoctor-diagram-layout
19
39
 
20
40
  ## Usage
21
41
 
22
- Register the extension and use the `[layout-rowcol]` block in your
23
- AsciiDoc documents:
42
+ Pass `-r asciidoctor-diagram-layout` to the Asciidoctor CLI:
24
43
 
25
- ```ruby
26
- require "asciidoctor"
27
- require "asciidoctor-diagram-layout"
44
+ ```
45
+ asciidoctor -r asciidoctor-diagram-layout doc.adoc
46
+ ```
47
+
48
+ ### Running from source
49
+
50
+ ```
51
+ bundle exec asciidoctor -r asciidoctor-diagram-layout doc.adoc
52
+ ```
53
+
54
+ ## Development
55
+
56
+ Install dependencies:
57
+
58
+ ```
59
+ bundle install
60
+ ```
61
+
62
+ Run tests:
63
+
64
+ ```
65
+ bundle exec rake spec
66
+ ```
67
+
68
+ Build the gem:
69
+
70
+ ```
71
+ bundle exec rake build
72
+ ```
73
+
74
+ ### Releasing a new version
75
+
76
+ 1. Update the version in `lib/asciidoctor_diagram_layout/version.rb`
77
+ 2. Update `CHANGELOG.md`
78
+ 3. Commit: `git commit -m "Release x.y.z"`
79
+ 4. Tag: `git tag vx.y.z`
80
+ 5. Push: `git push origin vx.y.z`
81
+
82
+ Requires `RUBYGEMS_API_KEY` secret configured in the repository settings.
83
+
84
+ **Locally** - build, tag, and publish in one command:
85
+
86
+ ```
87
+ bundle exec rake release
88
+ ```
89
+
90
+ Requires rubygems.org credentials (`gem signin`).
91
+
92
+ ## Examples
93
+
94
+
95
+ ### Single column layout
96
+
97
+ The simplest case: a vertical stack of areas.
98
+ Top-level cells without an explicit container are stacked
99
+ vertically by default.
100
+
101
+ ```asciidoc
102
+ [layout-rowcol, width="400px", height="200px"]
103
+ ----
104
+ cell: Header
105
+ cell: Content
106
+ cell: Footer
107
+ ----
108
+ ```
109
+
110
+ ![](examples/single-column.svg)
111
+
112
+ ### Fixed-size header and footer
113
+
114
+ A number in parentheses sets the size as a percentage of the
115
+ parent.
116
+ The remaining space is distributed equally among auto-sized
117
+ cells.
118
+
119
+ ```asciidoc
120
+ [layout-rowcol, width="400px", height="200px"]
121
+ ----
122
+ cell(20): Header
123
+ cell: Content
124
+ cell(20): Footer
125
+ ----
126
+ ```
127
+
128
+ ![](examples/fixed-size.svg)
129
+
130
+ ### Two-column layout with a sidebar
28
131
 
29
- Asciidoctor::Extensions.register do
30
- block AsciidoctorDiagramLayout::Asciidoc::LayoutBlockProcessor
31
- end
132
+ ```asciidoc
133
+ [layout-rowcol, width="400px", height="200px"]
134
+ ----
135
+ cols:
136
+ cell(25): Sidebar
137
+ cell: Content
138
+ ----
139
+ ```
140
+
141
+ ![](examples/sidebar.svg)
142
+
143
+ ### Classic page layout
144
+
145
+ A header and footer at fixed height, with a sidebar and main
146
+ content area in between.
147
+
148
+ ```asciidoc
149
+ [layout-rowcol, width="400px", height="250px"]
150
+ ----
151
+ cell(20): Header
152
+ cols:
153
+ cell(25): Sidebar
154
+ cell: Content
155
+ cell(20): Footer
156
+ ----
32
157
  ```
33
158
 
34
- ### Basic example
159
+ ![](examples/classic-page.svg)
160
+
161
+ ### Dashboard with nested sections
162
+
163
+ Nesting `rows:` and `cols:` containers produces complex grids.
164
+
165
+ ```asciidoc
166
+ [layout-rowcol, width="600px", height="350px"]
167
+ ----
168
+ cell(10): Toolbar
169
+ cols:
170
+ cell(20): Navigation
171
+ rows:
172
+ cell(30): Hero
173
+ cols:
174
+ cell: Features
175
+ cell: Pricing
176
+ cell: Testimonials
177
+ cell: Call to Action
178
+ cell(8): Footer
179
+ ----
180
+ ```
181
+
182
+ ![](examples/dashboard.svg)
183
+
184
+ ### Referencing document sections
185
+
186
+ Cell names support AsciiDoc `xref:` macros.
187
+ The cross-reference is preserved in HTML output and stripped to the
188
+ display label in SVG output.
35
189
 
36
190
  ```asciidoc
37
191
  [layout-rowcol]
38
192
  ----
193
+ cell(10): xref:header[Header]
39
194
  cols:
40
- cell(30): Sidebar
41
- rows:
42
- cell: Header
43
- cell: Content
195
+ cell(25): xref:sidebar[Sidebar]
196
+ cell: xref:content[Content]
197
+ cell(10): xref:footer[Footer]
44
198
  ----
45
199
  ```
46
200
 
47
- ### DSL syntax
201
+ ### Color palettes
48
202
 
49
- Each line declares one node. Indentation (4 spaces or one tab) defines
50
- nesting.
203
+ The `palette` attribute controls the color scheme.
204
+ Available values: `rainbow` (default), `warm`, `cool`, `mono`, `pastel`.
51
205
 
52
- * `cols:` - container that arranges children horizontally
53
- * `rows:` - container that arranges children vertically
54
- * `cell: Name` - leaf cell with a visible label
55
- * `cell(30): Name` - leaf cell with a fixed size of 30% of its parent
56
- * Containers without an explicit size take equal shares of the remaining
57
- space
58
- * Lines starting with `#` are comments
206
+ `warm`:
59
207
 
60
- ### Block attributes
208
+ ![](examples/palette-warm.svg)
61
209
 
62
- * `direction` - implicit direction for top-level cells when no container
63
- is declared: `rows` (default) or `cols`
64
- * `renderer` - force output format: `html` or `svg`; defaults to `html`
65
- for HTML backends and `svg` for all others including PDF
66
- * `palette` - color scheme: `rainbow` (default), `pastel`, `warm`,
67
- `cool`, `mono`
68
- * `width` - diagram width, e.g. `100%` (default) or `800px`
69
- * `height` - diagram height, e.g. `400px`; not set by default
70
- * `target` - SVG file name (without extension) when rendering to PDF
210
+ `cool`:
211
+
212
+ ![](examples/palette-cool.svg)
213
+
214
+ `mono`:
215
+
216
+ ![](examples/palette-mono.svg)
217
+
218
+ `pastel`:
219
+
220
+ ![](examples/palette-pastel.svg)
71
221
 
72
222
  ### PDF output
73
223
 
74
- When converting to PDF, the extension writes the diagram as an SVG file
75
- and embeds it as an image block.
76
- Use the `target` attribute to control the output file name:
224
+ When converting to PDF the diagram is written as an SVG file and
225
+ embedded as an image.
226
+ Use the `target` attribute to set the output file name:
77
227
 
78
228
  ```asciidoc
79
- [layout-rowcol, target="my-diagram"]
229
+ [layout-rowcol, target="page-layout"]
80
230
  ----
81
- cols:
82
- cell: Left
83
- cell: Right
231
+ cell(10): Header
232
+ cell: Content
233
+ cell(10): Footer
84
234
  ----
85
235
  ```
86
236
 
237
+ ## DSL syntax
238
+
239
+ Each line declares one node.
240
+ Indentation (4 spaces or one tab) defines nesting.
241
+
242
+ * `rows:` - container that arranges children vertically
243
+ * `cols:` - container that arranges children horizontally
244
+ * `cell: Name` - leaf cell with a visible label
245
+ * `cell(N): Name` - leaf cell with a fixed size of N% of its parent
246
+ * Containers and cells without an explicit size share the remaining
247
+ space equally
248
+ * Top-level nodes without an explicit container are wrapped in a
249
+ vertical (`rows`) container by default
250
+ * Lines starting with `#` are comments
251
+
252
+ ## Block attributes
253
+
254
+ * `direction` - implicit direction when no top-level container is
255
+ declared: `rows` (default) or `cols`
256
+ * `renderer` - force output format: `html` or `svg`; defaults to
257
+ `html` for HTML backends and `svg` for all others including PDF
258
+ * `palette` - color scheme: `rainbow` (default), `pastel`, `warm`,
259
+ `cool`, `mono`
260
+ * `width` - diagram width, e.g. `100%` (default) or `800px`
261
+ * `height` - diagram height, e.g. `400px`; not set by default
262
+ * `target` - SVG file name without extension, used when rendering
263
+ to PDF
264
+
87
265
  ## License
88
266
 
89
267
  Apache License 2.0.
@@ -7,26 +7,28 @@ module AsciidoctorDiagramLayout
7
7
  use_dsl
8
8
  named :"layout-rowcol"
9
9
  on_contexts :listing, :literal
10
+ name_positional_attributes "target"
10
11
 
11
12
  def process(parent, reader, attrs)
12
- dsl = reader.read
13
- implicit_dir = attrs["direction"] == "cols" ? :cols : :rows
14
- root = Parser.new.parse(dsl, implicit_dir)
15
- backend = parent.document.attr("backend").to_s
16
- renderer_attr = attrs["renderer"]
17
- strategy = resolve_strategy(renderer_attr, backend)
18
- palette = attrs.fetch("palette", "rainbow")
19
- pdf = backend == "pdf"
20
- options = Renderer::RenderOptions.new(
13
+ dsl = reader.read
14
+ implicit_dir = attrs["direction"] == "cols" ? :cols : :rows
15
+ root = Parser.new.parse(dsl, implicit_dir)
16
+ backend = parent.document.attr("backend").to_s
17
+ strategy = resolve_strategy(attrs["renderer"], backend)
18
+ palette = attrs.fetch("palette", "rainbow")
19
+ pdf = backend == "pdf"
20
+ title = attrs["title"]
21
+ options = Renderer::RenderOptions.new(
21
22
  width: attrs.fetch("width", "100%"),
22
23
  height: attrs["height"],
24
+ title: title,
23
25
  palette: palette,
24
26
  pdf: pdf,
25
- name_converter: method(:identity)
27
+ name_converter: ->(name) { convert_inline(parent, name) }
26
28
  )
27
29
  case strategy
28
30
  when :html then render_html(parent, root, options)
29
- when :svg then render_svg(parent, root, backend, options, attrs)
31
+ when :svg then render_svg(parent, root, backend, options, attrs, title)
30
32
  end
31
33
  end
32
34
 
@@ -49,16 +51,17 @@ module AsciidoctorDiagramLayout
49
51
  create_pass_block(parent, html, {}, subs: nil)
50
52
  end
51
53
 
52
- def render_svg(parent, root, backend, options, attrs)
53
- svg = Renderer::SvgRenderer.new.render(root, options)
54
- if backend == "pdf"
55
- target = attrs["target"]
56
- outdir = parent.document.attr("outdir").to_s
57
- path = write_svg(svg, target, outdir)
58
- create_image_block(parent, { "target" => path, "format" => "svg" })
59
- else
60
- create_pass_block(parent, svg, {}, subs: nil)
61
- end
54
+ def render_svg(parent, root, backend, options, attrs, title)
55
+ svg = Renderer::SvgRenderer.new.render(root, options)
56
+ target = attrs["target"]
57
+ outdir = parent.document.attr("outdir").to_s
58
+ path = write_svg(svg, target, outdir)
59
+ filename = File.basename(path)
60
+ parent.document.register(:images, filename)
61
+ img_target = backend == "pdf" ? File.expand_path(path) : filename
62
+ block = create_image_block(parent, { "target" => img_target, "format" => "svg" })
63
+ block.title = title if title && !title.empty?
64
+ block
62
65
  end
63
66
 
64
67
  def write_svg(svg, name, outdir)
@@ -75,8 +78,9 @@ module AsciidoctorDiagramLayout
75
78
  path
76
79
  end
77
80
 
78
- def identity(text)
79
- text
81
+ def convert_inline(node, text)
82
+ escaped = node.sub_specialchars(text)
83
+ node.sub_macros(escaped)
80
84
  end
81
85
  end
82
86
  end
@@ -13,7 +13,12 @@ module AsciidoctorDiagramLayout
13
13
  sb << "<div style=\"#{wrapper_style}\">\n"
14
14
  render_node(root, sb, 1, options)
15
15
  sb << "</div>\n"
16
- sb
16
+ if options.title && !options.title.empty?
17
+ "<div class=\"imageblock\">\n<div class=\"content\">\n#{sb}</div>\n" \
18
+ "<div class=\"title\">#{options.title}</div>\n</div>"
19
+ else
20
+ sb
21
+ end
17
22
  end
18
23
 
19
24
  private
@@ -1,12 +1,13 @@
1
1
  module AsciidoctorDiagramLayout
2
2
  module Renderer
3
3
  class RenderOptions
4
- attr_reader :width, :height, :color_scheme, :name_converter
4
+ attr_reader :width, :height, :title, :color_scheme, :name_converter
5
5
 
6
- def initialize(width: "100%", height: nil, palette: "rainbow", pdf: false,
6
+ def initialize(width: "100%", height: nil, title: nil, palette: "rainbow", pdf: false,
7
7
  color_scheme: nil, name_converter: nil)
8
8
  @width = width
9
9
  @height = height
10
+ @title = title
10
11
  @color_scheme = color_scheme || Scheme::CellColorSchemeFactory.resolve(palette, pdf: pdf)
11
12
  @name_converter = name_converter || method(:escape)
12
13
  end
@@ -17,6 +17,9 @@ module AsciidoctorDiagramLayout
17
17
  sb << " height=\"#{h}\""
18
18
  sb << " style=\"font-family:sans-serif;\""
19
19
  sb << ">\n"
20
+ if options.title && !options.title.empty?
21
+ sb << " <title>#{escape_xml(options.title)}</title>\n"
22
+ end
20
23
  if defs.length > 0
21
24
  sb << " <defs>\n" << defs << " </defs>\n"
22
25
  end
@@ -1,3 +1,3 @@
1
1
  module AsciidoctorDiagramLayout
2
- VERSION = "1.0.1"
2
+ VERSION = "1.1.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asciidoctor-diagram-layout
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anton Pechinsky
@@ -13,14 +13,14 @@ dependencies:
13
13
  name: asciidoctor
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
- - - ">="
16
+ - - "~>"
17
17
  - !ruby/object:Gem::Version
18
18
  version: '2.0'
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
- - - ">="
23
+ - - "~>"
24
24
  - !ruby/object:Gem::Version
25
25
  version: '2.0'
26
26
  - !ruby/object:Gem::Dependency
@@ -37,6 +37,34 @@ dependencies:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
39
  version: '3.0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: rake
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '13.0'
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '13.0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: erb
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
40
68
  description: Provides a [layout] block for Asciidoctor that renders layout diagrams
41
69
  as HTML or SVG.
42
70
  email: anton@pechinsky.com
@@ -69,7 +97,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
69
97
  requirements:
70
98
  - - ">="
71
99
  - !ruby/object:Gem::Version
72
- version: '0'
100
+ version: '2.7'
73
101
  required_rubygems_version: !ruby/object:Gem::Requirement
74
102
  requirements:
75
103
  - - ">="