Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ On the **display page** (where the saved content is shown to readers), resolve
the stored rich text. This is what swaps each variable chip for its value:

```erb
<%= render_lexxy_content(@record.body) %>
<%= render_variable_content(@record.body) %>
```

Each chip resolves to its value, so the reader sees finished text:
Expand Down Expand Up @@ -152,7 +152,7 @@ Editor page:
Display page:

```erb
<%= render_lexxy_content(@message.body,
<%= render_variable_content(@message.body,
first_name: @user.first_name,
last_name: @user.last_name) %>
```
Expand All @@ -170,7 +170,7 @@ end
```

```erb
<%= render_lexxy_content(@message.body) %>
<%= render_variable_content(@message.body) %>
```

### Liquid drops and dotted access
Expand Down Expand Up @@ -207,7 +207,7 @@ end
```

```erb
<%= render_lexxy_content(@message.body) %>
<%= render_variable_content(@message.body) %>
```

A `user.first_name` chip becomes `{{ user.first_name }}`, which Liquid runs through the drop. Only the methods defined on the drop are reachable, not arbitrary attributes on the user. Liquid doesn't escape output the way the default renderer does, so the drop escapes its own values. The same goes for any plain string returned from `assigns` or passed inline.
Expand Down Expand Up @@ -242,7 +242,7 @@ end
| Option | Default | What it does |
| --- | --- | --- |
| `catalog` | `[]` | The insertable items shown in the `{{` prompt and the toolbar dropdown. A list, a zero-arg lambda, or a `->(context)` lambda. Items respond to `#key` and `#name`, and optionally `#value` and `#attachable_sgid`. |
| `assigns` | reads `#value` off catalog items | The render-time lookup. A `->(context, used_keys)` or `->(used_keys)` lambda that receives only the keys used in the content being rendered and returns a `{ key => value }` hash. Per-render values can also be passed straight to `render_lexxy_content` (see [Helper options](#helper-options)). |
| `assigns` | reads `#value` off catalog items | The render-time lookup. A `->(context, used_keys)` or `->(used_keys)` lambda that receives only the keys used in the content being rendered and returns a `{ key => value }` hash. Per-render values can also be passed straight to `render_variable_content` (see [Helper options](#helper-options)). |
| `renderer` | `Renderers::Substitution.new` | How placeholders become values. The default is plain, escaped string substitution with no template engine. Swap in `Renderers::Liquid.new` for dotted access, drops, and filters. |
| `sort` | `:name` | How the catalog is ordered in the prompt and dropdown. `:name` (case-insensitive alphabetical), `:key`, `false` to keep the catalog's given order, or a lambda (a `->(item)` sort key or a `->(a, b)` comparator). |
| `max_fragment_depth` | `1` | How many levels of `renders_as: :html` chips expand. The default resolves the variables inside a snippet but drops a snippet nested inside another snippet. Raise it to allow deeper nesting. |
Expand All @@ -253,26 +253,26 @@ end

Both view helpers take `context:` (see [Multi-tenancy](#multi-tenancy)). Beyond
that, `lexxy_variables_prompt` lets you change the trigger characters and the
empty state, and `render_lexxy_content` can render under a specific locale by
empty state, and `render_variable_content` can render under a specific locale by
wrapping the whole pass in `I18n.with_locale`.

```erb
<%= lexxy_variables_prompt(trigger: "%%", empty_results: t(".no_variables")) %>

<%= render_lexxy_content(@record.body, locale: recipient.locale) %>
<%= render_variable_content(@record.body, locale: recipient.locale) %>
```

You can also pass a variable's value straight to `render_lexxy_content`, as
You can also pass a variable's value straight to `render_variable_content`, as
keyword arguments or an `assigns:` hash. These win over whatever the configured
`assigns` returns, and a value for a key that isn't used in the content is just
ignored:

```erb
<%# keyword arguments %>
<%= render_lexxy_content(@record.body, first_name: @user.first_name) %>
<%= render_variable_content(@record.body, first_name: @user.first_name) %>

<%# same thing, for a name that would clash with context: or locale: %>
<%= render_lexxy_content(@record.body, assigns: { first_name: @user.first_name }) %>
<%= render_variable_content(@record.body, assigns: { first_name: @user.first_name }) %>
```

The default renderer escapes these values for you. Liquid doesn't, so escape
Expand Down Expand Up @@ -301,7 +301,7 @@ Both view helpers take the same `context:`. Pass the tenant on the editor page:
and again on the display page:

```erb
<%= render_lexxy_content(@record.body, context: ActsAsTenant.current_tenant) %>
<%= render_variable_content(@record.body, context: ActsAsTenant.current_tenant) %>
```

Or skip `context` entirely and rely on acts_as_tenant scoping queries to the
Expand Down
4 changes: 2 additions & 2 deletions lib/lexxy_variables/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ module Helper
# `assigns:` (and any extra keyword args) are per-render values merged on top
# of the configured `assigns`, so a caller can supply a key's value inline:
#
# render_lexxy_content(@record.body, first_name: @user.first_name)
# render_variable_content(@record.body, first_name: @user.first_name)
#
# Inline values win over the configured assigns. Keys not used by any chip in
# the body are ignored. Under the default renderer inline values are
# HTML-escaped; under Liquid they are emitted as-is, so pre-escape them or
# pass a drop.
def render_lexxy_content(rich_text, context: nil, locale: I18n.locale, assigns: {}, **inline_assigns)
def render_variable_content(rich_text, context: nil, locale: I18n.locale, assigns: {}, **inline_assigns)
LexxyVariables::Pipeline.new(self).call(
rich_text, context: context, locale: locale, assigns: assigns.merge(inline_assigns)
)
Expand Down
10 changes: 5 additions & 5 deletions test/helper_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Unit-tests the view helper's argument handling in isolation. The pipeline is
# swapped for a fake that captures what it is called with, so these assert how
# render_lexxy_content forwards context, locale, and inline assigns without
# render_variable_content forwards context, locale, and inline assigns without
# exercising the full ActionText render path (that lives in pipeline_test).
class HelperTest < Minitest::Test
class FakePipeline
Expand Down Expand Up @@ -43,25 +43,25 @@ def last_assigns
end

def test_keyword_args_become_inline_assigns
View.new.render_lexxy_content(:body, first_name: "Ada")
View.new.render_variable_content(:body, first_name: "Ada")

assert_equal({ first_name: "Ada" }, last_assigns)
end

def test_explicit_assigns_hash_is_passed_through
View.new.render_lexxy_content(:body, assigns: { first_name: "Ada" })
View.new.render_variable_content(:body, assigns: { first_name: "Ada" })

assert_equal({ first_name: "Ada" }, last_assigns)
end

def test_explicit_and_keyword_assigns_are_merged
View.new.render_lexxy_content(:body, assigns: { first_name: "Ada" }, last_name: "Lovelace")
View.new.render_variable_content(:body, assigns: { first_name: "Ada" }, last_name: "Lovelace")

assert_equal({ first_name: "Ada", last_name: "Lovelace" }, last_assigns)
end

def test_context_and_locale_are_not_swallowed_into_assigns
View.new.render_lexxy_content(:body, context: :tenant, locale: :fr, plan: "pro")
View.new.render_variable_content(:body, context: :tenant, locale: :fr, plan: "pro")

kwargs = @fake.calls.last.last
assert_equal :tenant, kwargs[:context]
Expand Down
Loading