serbea 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/docs/src/index.md DELETED
@@ -1,276 +0,0 @@
1
- ---
2
- layout: home
3
- ---
4
-
5
- ### Serbea is the Ruby template engine you didn't realize you needed. Until now.
6
- {:.no_toc}
7
-
8
- **Serbea** combines the best ideas from "brace-style" template languages such as Liquid, Nunjucks, Twig, Jinja, Mustache, etc.—and applies them to the world of **ERB**. You can use Serbea in Rails applications, Bridgetown static sites, or pretty much any Ruby scenario you could imagine.
9
-
10
- **Serbea**. Finally, something to crow(n) about. _Le roi est mort, vive le roi!_
11
-
12
- ### Table of Contents
13
- {:.no_toc}
14
- * …
15
- {:toc}
16
-
17
- ### Features and Syntax
18
-
19
- {% raw %}
20
-
21
- * **Real Ruby**. Like, for real.
22
- * Supports every convention of ERB and builds upon it with new features (which is why it's "awesomer!").
23
- * Filters! Frontmatter!! Pipeline operators!!! 🤩
24
- * The filters accessible within Serbea templates are either traditional helpers (where the variable gets passed as the first argument) or _instance methods of the variable itself_. So you can build extremely expressive pipelines that take advantage of the code you already know and love.
25
-
26
- For example, in Rails you could write: `{{ "My Link" | sub: "Link", "Page" | link_to: route_path }}`.
27
- * The `Serbea::Pipeline.exec` method lets you pass a pipeline template in, along with an optional input value or included helpers module, and you'll get the output as a object of any type (not converted to a string like in traditional templates).
28
-
29
- For example:
30
-
31
- `Serbea::Pipeline.exec %( arr |> map: ->(i) { i * 10 } ), arr: [1,2,3]`
32
-
33
- will return:
34
-
35
- `[10, 20, 30]`
36
-
37
- * Serbea will HTML autoescape variables by default within pipeline (`{{ }}`) tags. Use the `safe` / `raw` or `escape` / `h` filters to control escaping on output.
38
- * Directives apply handy shortcuts that modify the template at the syntax level before processing through Ruby.
39
-
40
- `{%@ %}` is a shortcut for rendering either string-named partials (`render "tmpl"`) or object instances (`render MyComponent.new`). And in Rails, you can use new Turbo Stream directives for extremely consise templates:
41
-
42
- ```serb
43
- {%@remove "timeline-read-more" %}
44
- {%@append "timeline" do %}
45
- {%@ partial: "posts", formats: [:html] %}
46
- {% end %}
47
- ```
48
- * Built-in frontmatter support. Now you can access the variables written into a top YAML block within your templates. In any Rails view, including layouts, you'll have access to the `@frontmatter` ivar which is a merged `HashWithDotAccess::Hash` with data from any part of the view tree (partials, pages, layout).
49
-
50
- For example, you could put `<title>{{ @frontmatter.title }}</title>` in your head partial, and then each page could define `title` frontmatter individually. You can even use Ruby string interpolation within the YAML so titles and other metadata can come from `t` language helpers.
51
- * Define macros/helpers which can be imported and used within Serbea templates.
52
-
53
- ```serb
54
- <!-- _macros.serb -->
55
- {% macro :greet do |name:| %}
56
- {{ name }}, my old friend!
57
- {% end %}
58
-
59
- <!-- tmpl.serb -->
60
- {% import "macros" %}
61
-
62
- Hello {{ greet(name: "darkness") }}
63
- ```
64
-
65
- {% endraw %}
66
-
67
- ### What Serbea Looks Like
68
-
69
- {% raw %}
70
-
71
- ```serb
72
- <!-- example.serb -->
73
-
74
- {% wow = capture do %}
75
- This is {{ "amazing" + "!" | upcase }}
76
- {% end %}
77
-
78
- {% wow = wow.each_char.reduce("") do |newstr, c|
79
- newstr += " #{c}"
80
- end.strip %}
81
-
82
- {{ wow | prepend: "OMG! " }}
83
- ```
84
-
85
- Use `helper` (alias `macro`) to create ad-hoc filters:
86
-
87
- ```serb
88
- <p>
89
- {%
90
- helper :multiply_array do |input, multiply_by = 2|
91
- input.map do |i|
92
- i.to_i * multiply_by
93
- end
94
- end
95
- %}
96
-
97
- Multiply! {{ [1,3,6, "9"] | multiply_array: 10 }}
98
- </p>
99
- ```
100
-
101
- Forms, partials, etc. No sweat!
102
-
103
- ```serb
104
- {%= form classname: "checkout" do |f| %}
105
- {{ f.input :first_name, required: true | errors: error_messages }}
106
- {% end %}
107
-
108
- {%= render "box" do %}
109
- This is **dope!**
110
- {%= render "card", title: "Nifty!" do %}
111
- So great.
112
- {% end %}
113
- {% end %}
114
- ```
115
-
116
- Let's simplify that using the render directive!
117
-
118
- ```serb
119
- {%@ "box" do %}
120
- This is **dope!**
121
- {%@ "card", title: "Nifty!" do %}
122
- So great.
123
- {% end %}
124
- {% end %}
125
- ```
126
-
127
- Works with ViewComponent! And we can use the render directive!
128
-
129
- ```serb
130
- {%@ Theme::DropdownComponent name: "banner", label: "Banners" do |dropdown| %}
131
- {% RegistryTheme::BANNERS.each do |banner| %}
132
- {% dropdown.slot(:item, value: banner) do %}
133
- <img src="{{ banner | parameterize: separator: "_" | prepend: "/themes/" | append: ".jpg" }}">
134
- <strong>{{ banner }}</strong>
135
- {% end %}
136
- {% end %}
137
- {% end %}
138
- ```
139
-
140
- The `|` and `|>` pipeline operators are equivalent, so you can write like this if you want!
141
-
142
- ```serb
143
- {{
144
- [1,2,3] |>
145
- map: -> i { i * 10 }
146
- |>
147
- filter: -> i do
148
- i > 15 # works fine with multiline blocks
149
- end
150
- |>
151
- assign_to: :array_length
152
- }}
153
-
154
- Array length: {{ @array_length.length }}
155
- ```
156
- {% endraw %}
157
-
158
- {{
159
- [1,2,3] |>
160
- map: -> i { i * 10 }
161
- |>
162
- filter: -> i do
163
- i > 15 # works fine with multiline blocks
164
- end
165
- |>
166
- assign_to: :array_length
167
- }}
168
-
169
- The answer of course is: **{{ @array_length.length }}**
170
-
171
- ### Installation and Usage
172
-
173
- Simply add the Serbea gem to your `Gemfile`:
174
-
175
- ```
176
- bundle add serbea
177
- ```
178
-
179
- or install standalone:
180
-
181
- ```
182
- gem install serbea
183
- ```
184
-
185
- If you're using [Bridgetown](https://www.bridgetownrb.com), make sure it's included in the `bridgetown_plugins` group.
186
-
187
- Serbea templates are typically saved using a `.serb` extension. If you use VS Code as your editor, there is a [VS Code extension](https://marketplace.visualstudio.com/items?itemName=whitefusion.serbea) to enable Serbea syntax highlighting as well as palette commands to convert selected ERB syntax to Serbea.
188
-
189
- To convert Serbea code in a basic Ruby script, all you have to do is require the Serbea gem, include the necessary helpers module, and use the Tilt interface to load and render the template. Example:
190
-
191
- {% raw %}
192
- ```ruby
193
- require "serbea"
194
- include Serbea::Helpers
195
-
196
- tmpl = Tilt::SerbeaTemplate.new { "Hello {{ world | append: '!' }}" }
197
- tmpl.render(self, world: "World")
198
-
199
- # Hello World!
200
- ```
201
-
202
- You'll likely want to bind to a dedicated view object instead of `self` as in the example above, since that view object can include the Serbea helpers without fear of any collision with existing object methods in your codebase.
203
-
204
- Serbea helpers include `pipeline` which faciliates the `{{ }}` template syntax, `capture`, `helper`, `safe`, `escape`, and `assign_to`.
205
- {% endraw %}
206
-
207
- ### Rails Support
208
-
209
- Serbea fully supports Rails (tested with Rails 6), and even includes special directives for Turbo Streams as highlighted above.
210
-
211
- Simply use the `.serb` extension wherever you would use `.erb` normally. You can freely mix 'n' match Serbea templates with other template engines, so for instance `index.html.erb` and `show.html.serb` can live side-by-side.
212
-
213
- **Note:** if you use a Serbea template as a _layout_, you may encounter some subtle rendering issues with ERB page templates that use the layout. It is recommended you use Serbea for layouts only if you intend to standardize on Serbea for your application.
214
-
215
- **Upgrade your helpers!** While you can use the same kind of syntax for helpers you may be accustomed to in ERB, using the pipeline syntax can be far more enjoyable and better express intent. For example, instead of confusing nested method calls like this:
216
-
217
- {% raw %}
218
- ```erb
219
- Here's a <%= link_to(highlight(" link for you ".strip.titleize, "you"), other_page_path) %>.
220
- ```
221
-
222
- You could instead write this:
223
-
224
- ```serb
225
- Here's a {{ " link for you " | strip | titleize | highlight: "you" | link_to: other_page_path }}
226
- ```
227
-
228
- which is _far_ easier to parse visually and less likely to cause bugs due to nesting errors.
229
-
230
- **Stay Safe!** In pipelines, Serbea uses the same safe escaping logic you've experienced with ERB. So if you were to put `{{ "<p>Aha!</p>" }}` in a template, you don't get an HTML paragraph, you get the literal characters of the p tags. You would have to use the `safe` (aliased `raw`) filter in order to get working HTML output. _However_, that is NOT the case with expressions. `{%= "<p>Bingo!</p>" %}` outputs that text verbatim and you get a valid HTML paragraph. So use expressions sparingly and only in cases where you know the values have already been cleansed (e.g., rendering partials or components, using form helpers, yielding in layouts, etc.). Alternatively, you can use the `escape` (aliased `h`) helper: `{%= escape "<p>Bingo!</p>" %}`.
231
-
232
- {% endraw %}
233
-
234
- ### Bridgetown Support
235
-
236
- Serbea fully supports [Bridgetown](https://www.bridgetownrb.com). In fact, Serbea is an excellent upgrade from Liquid as the syntax initially looks familar, yet it enbles the full power of real Ruby in your templates.
237
-
238
- Out of the box, you can name pages and partials with a `.serb` extension. But for even more flexibility, you can add `template_engine: serbea` to your `bridgetown.config.yml` configuration. This will default all pages and documents to Serbea unless you specifically use front matter to choose a different template engine (or use an extension such as `.liquid` or `.erb`).
239
-
240
- Here's an abreviated example of what the Post layout template looks like on the [RUBY3.dev](https://www.ruby3.dev) blog:
241
-
242
- {% raw %}
243
- ```serb
244
- ---
245
- layout: bulmatown/post
246
- ---
247
-
248
- <div class="content-column">{%= yield %}</div>
249
-
250
- {{ liquid_render "subscribe" }}
251
-
252
- {% if page.data.image_credit %}
253
- <p class="mt-6 is-size-7 has-text-centered">
254
- <em>Banner image by <a href="{{ page.data.image_credit.url | safe }}">
255
- {{ page.data.image_credit.label }}
256
- </a></em>
257
- </p>
258
- {% end %}
259
-
260
- {% posts = page.related_posts[0...2] %}
261
- {{ liquid_render "bulmatown/collection", collection: posts, metadata: site.metadata }}
262
-
263
- {% if page.related_posts.size > 2 %}
264
- <a href="/articles">Read More Articles</a>
265
- {% end %}
266
-
267
- {%= markdownify do %}
268
- {{ liquid_render "sponsor" }}
269
- {% end %}
270
- ```
271
- {% endraw %}
272
-
273
-
274
- ### How Pipelines Work Under the Hood
275
-
276
- Documentation forthcoming!
data/docs/start.js DELETED
@@ -1,17 +0,0 @@
1
- const concurrently = require('concurrently');
2
-
3
- // By default, configure Bridgetown to use port 4001 so Browsersync can use 4000
4
- // See also Browsersync settings in sync.js
5
- const port = 4001
6
-
7
- /////////////////
8
- // Concurrently
9
- /////////////////
10
- concurrently([
11
- { command: "yarn webpack-dev", name: "Webpack", prefixColor: "yellow"},
12
- { command: "sleep 4; yarn serve --port " + port, name: "Bridgetown", prefixColor: "green"},
13
- { command: "sleep 8; yarn sync", name: "Live", prefixColor: "blue"}
14
- ], {
15
- restartTries: 3,
16
- killOthers: ['failure', 'success'],
17
- }).then(() => { console.log("Done.");console.log('\033[0G'); }, () => {});
data/docs/sync.js DELETED
@@ -1,35 +0,0 @@
1
- const browserSync = require("browser-sync").create();
2
-
3
- // You can change these configuration values:
4
- const proxy = "http://localhost:4001"
5
- const port = 4000
6
- const uiPort = 4002
7
-
8
- ////////////////
9
- // Browsersync
10
- ////////////////
11
- browserSync.init({
12
- open: false,
13
- notify: false,
14
- proxy: proxy,
15
- port: port,
16
- files: "output/index.html",
17
- ghostMode: {
18
- clicks: false,
19
- forms: false,
20
- scroll: false,
21
- },
22
- reloadDelay: 0,
23
- injectChanges: false,
24
- ui: {
25
- port: uiPort
26
- },
27
- snippetOptions: {
28
- rule: {
29
- match: /<\/head>/i,
30
- fn: function (snippet, match) {
31
- return snippet + match;
32
- },
33
- },
34
- },
35
- });
@@ -1,78 +0,0 @@
1
- const path = require("path");
2
- const MiniCssExtractPlugin = require("mini-css-extract-plugin");
3
- const ManifestPlugin = require("webpack-manifest-plugin");
4
-
5
- module.exports = {
6
- entry: "./frontend/javascript/index.js",
7
- devtool: "source-map",
8
- // Set some or all of these to true if you want more verbose logging:
9
- stats: {
10
- modules: false,
11
- builtAt: false,
12
- timings: false,
13
- children: false,
14
- },
15
- output: {
16
- path: path.resolve(__dirname, "output", "_bridgetown", "static", "js"),
17
- filename: "all.[contenthash].js",
18
- },
19
- resolve: {
20
- extensions: [".js", ".jsx"],
21
- },
22
- plugins: [
23
- new MiniCssExtractPlugin({
24
- filename: "../css/all.[contenthash].css",
25
- }),
26
- new ManifestPlugin({
27
- fileName: path.resolve(__dirname, ".bridgetown-webpack", "manifest.json"),
28
- }),
29
- ],
30
- module: {
31
- rules: [
32
- {
33
- test: /\.(js|jsx)/,
34
- use: {
35
- loader: "babel-loader",
36
- options: {
37
- presets: ["@babel/preset-env"],
38
- plugins: [
39
- ["@babel/plugin-proposal-decorators", { "legacy": true }],
40
- ["@babel/plugin-proposal-class-properties", { "loose" : true }],
41
- [
42
- "@babel/plugin-transform-runtime",
43
- {
44
- helpers: false,
45
- },
46
- ],
47
- ],
48
- },
49
- },
50
- },
51
- {
52
- test: /\.(s[ac]|c)ss$/,
53
- use: [
54
- MiniCssExtractPlugin.loader,
55
- "css-loader",
56
- {
57
- loader: "sass-loader",
58
- options: {
59
- sassOptions: {
60
- includePaths: [
61
- path.resolve(__dirname, "src/_components")
62
- ],
63
- },
64
- },
65
- },
66
- ],
67
- },
68
- {
69
- test: /\.woff2?$|\.ttf$|\.eot$|\.svg$/,
70
- loader: "file-loader",
71
- options: {
72
- outputPath: "../fonts",
73
- publicPath: "../fonts",
74
- },
75
- },
76
- ],
77
- },
78
- };