slime-lang / phoenix_slime Goto Github PK
View Code? Open in Web Editor NEWPhoenix Template Engine for Slime
License: MIT License
Phoenix Template Engine for Slime
License: MIT License
Hello,
I'm just trying out Slime and while converting my app.html.eex
file I found out that if I write this:
doctype html
html
I get an error like:
Compiling 1 file (.ex)
== Compilation error in file lib/rumbl_web/views/layout_view.ex ==
** (Slime.TemplateSyntaxError) Unexpected symbol '
'
INPUT, Line 2, Column 1
Notice the empty line between doctype
and html
.
If I remove the space everything is ok.
It also works like this:
doctype html
|
html
Is there any particular reason why an empty line is not allowed between the doctype
and html
tags?
Hello!
I am getting error
Please pass a `->` clause to do/end instead, for example:
live_component @socket, GridComponent, entries: @entries do
new_assigns -> "New entry: " <> new_assigns[:entry]
end
When I try to use do block to pass content to child component.
What is the correct syntax in PhoenixSlime?
p.alert.alert-danger role="alert"= get_flash(@conn, :error)
main role="main"
= render @view_module, @view_template, assigns
Vs
p.alert.alert-danger role="alert"= get_flash(@conn, :error)
main role="main"
= render @view_module, @view_template, assigns
The second case renders <p></p>
with a newline inside the block. With Phoenix's default CSS, this is non-empty, so the alert box is always shown even when there is no error.
Is there a way to prevent Slime from treating the newline as significant?
Can you please push a new version to hex so we can use with phoenix 1.3. Thanks...
Couldn't find an official solution for this.
{:phoenix_slime, "~> 0.10.0"}
$ mix deps.get
Failed to use "cowboy" (version 2.5.0) because
phoenix_slime (versions 0.10.0 and 0.10.1) requires ~> 1.0
plug_cowboy (version 2.0.0) requires ~> 2.5
mix.lock specifies 2.5.0
** (Mix) Hex dependency resolution failed, change the version requirements of your dependencies or unlock them (by using mix deps.update or mix deps.unlock). If you are unable to resolve the conflicts you can try overriding with {:dependency, "~> 1.0", override: true}
If I use the master branch.
{:phoenix_slime, github: "slime-lang/phoenix_slime"}
$ mix deps.get
Failed to use "cowboy" (versions 1.0.0 to 1.1.2) because
deps/phoenix_slime/mix.exs requires ~> 1.0
plug_cowboy (version 2.0.0) requires ~> 2.5
I attempted to create a scoped style tag using the css:
prefix. Based on what I've read about slim, it should support css class="myClass"
, but when I attempt to use it like this:
css class="test":
p { background-color: blue; }
it renders like this:
<css class="test">:
p { background-color: blue; }
</css>
Hi,
I was wondering if there is already support for rendering partials ?
/Gerard
I have this line:
option(value="#{page_size}") =page_size
and I'm trying to add selected
attribute to selected option like here:
option(value="#{page_size}" ="#{page_size == @page.size && 'selected' || ''}") =page_size
but I get this error when I try:
Compiling 1 file (.ex)
== Compilation error in file lib/app_web/views/user_view.ex ==
** (Slime.TemplateSyntaxError) Unexpected indent
INPUT, Line 31, Column 0
select(name="page_size")
^
(slime) lib/slime/parser.ex:14: Slime.Parser.parse/1
(slime) lib/slime/renderer.ex:17: Slime.Renderer.precompile/1
(phoenix_slime) lib/phoenix_slime/live_view_engine.ex:9: PhoenixSlime.LiveViewEngine.compile/2
(phoenix) lib/phoenix/template.ex:355: Phoenix.Template.compile/3
(phoenix) lib/phoenix/template.ex:166: anonymous fn/4 in Phoenix.Template."MACRO-__before_compile__"/2
(elixir) lib/enum.ex:1948: Enum."-reduce/3-lists^foldl/2-0-"/3
(phoenix) expanding macro: Phoenix.Template.__before_compile__/1
lib/app_web/views/user_view.ex:1: AppWeb.UserView (module)
(elixir) lib/kernel/parallel_compiler.ex:229: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/7
Compiling 1 file (.ex)
How can I do this?
I'm trying to assign a CSS class inline from a method call, but it doesn't work.
Is that supported in Slime?
li[class="#{active_link(@conn, :about)}"]
Hi, I've updated my mix.exs
to fetch phoenix_slime
right from repo:
{:phoenix_slime, github: "slime-lang/phoenix_slime", override: true}
But it produces syntax error on compilation.
Any ideas why? Maybe related to recent update of slime version?
== Compilation error on file lib/myproject/web/views/layout_view.ex ==
** (Slime.TemplateSyntaxError) {:no_match, "\n"}
INPUT, Line 1, Column 1
^
lib/slime/parser.ex:27: Slime.Parser.handle_syntax_error/3
lib/slime/renderer.ex:17: Slime.Renderer.precompile/1
lib/phoenix_slime/engine.ex:9: PhoenixSlime.Engine.compile/2
(phoenix) lib/phoenix/template.ex:378: Phoenix.Template.compile/2
(phoenix) lib/phoenix/template.ex:186: Phoenix.Template."-MACRO-__before_compile__/2-fun-0-"/3
(elixir) lib/enum.ex:1755: Enum."-reduce/3-lists^foldl/2-0-"/3
(phoenix) expanding macro: Phoenix.Template.__before_compile__/1
lib/myproject/web/views/layout_view.ex:1: MyProject.Web.LayoutView (module)
(elixir) lib/kernel/parallel_compiler.ex:117: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/1
My elixir version:
Erlang/OTP 20 [erts-9.0] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
Elixir 1.4.5
Is Slime compatible with Elixir 1.8? It looks like EEx.Engine.handle_begin/1
implementation changed from ignoring the argument and returning an empty string, to expecting a map and raising a bad map error because it's called with a tuple, e.g. {:safe, [{:|, [], ["", "<h1>Reset your password</h1>"]}]}
Phoenix 0.16 (and LiveView 0.16) introduce HEEx, which is a huge step forward, enabling semantic HTML parsing/validation.
I depend on phoenix_slime and am hopeful that the library can be updated to support HEEx. The main issues I see are:
{ }
syntax for attributes.form
)Since HAML/Slim/Slime reserve the dot for classes, it seems that this new convention in HEEx may be directly incompatible with Slim/Slime as we've known it. Hopefully there's some way to support it.
For anyone close to the code in this library, do you have a sense of what it would take to upgrade phoenix_slime to support the latest incarnations of Phoenix/LiveView/HEEx?
String interpolation in input value works like without interpolation, e.g.
- foo = "bar"
- form_ok = Phoenix.HTML.Tag.content_tag(:form) do
input name="test" value="val"
p "#{foo}"
= form_ok
Renders
<p>bar</p>
<form>
<input name="test" value="val">
</form>
- foo = "bar"
- form_not_ok = Phoenix.HTML.Tag.content_tag(:form) do
input name="test" value="#{foo}"
p "#{foo}"
= form_not_ok
Renders
<input name="test"<p>bar</p>
<form>
<input name="test" value="bar">
</form>
==> phoenix_slime
Compiling 4 files (.ex)
warning: function Mix.Phoenix.copy_from/5 is undefined or private. Did you mean one of:
* copy_from/4
Found at 2 locations:
lib/mix/tasks/phoenix.gen.html.slime.ex:54
lib/mix/tasks/phoenix.gen.html.slime.ex:60
warning: function Mix.Phoenix.copy_from/5 is undefined or private. Did you mean one of:
* copy_from/4
lib/mix/tasks/phoenix.gen.layout.slime.ex:16
Freshly created Phoenix project, when trying to run mix phoenix.gen.layout.slime
I'm receiving this error
** (UndefinedFunctionError) function Mix.Phoenix.copy_from/5 is undefined or private. Did you mean one of:
* copy_from/4
Mix.Phoenix.copy_from([".", :phoenix_slime], "priv/templates/phoenix.gen.layout.slime", "", [application_module: "ApplicationName"], [{:eex, "app.html.eex", "web/templates/layout/app.html.slim"}])
lib/mix/tasks/phoenix.gen.layout.slime.ex:16: Mix.Tasks.Phoenix.Gen.Layout.Slime.run/1
(mix) lib/mix/task.ex:301: Mix.Task.run_task/3
(mix) lib/mix/cli.ex:75: Mix.CLI.run_task/2
(elixir) lib/code.ex:376: Code.require_file/2
I have this:
javascript:
var something = {
var1: #{Application.get_env(:aaa, :bbb)},
var2: true,
var3: false,
var4: {
env: "prod"
}
};
(somefunction() { .... /* some code */ })
The output code it produces contains html tags, including tags that don't exist in html, and other kinds of crazy stuff and it's not valid js code.
This
javascript:
alert('Slim supports embedded javascript!')
produces this
<javascript><alert 'Slim supports embedded javascript!'></alert></javascript>
I could try to add this feature for upcoming Phoenix 1.4 release.
# Phoenix 1.3
static_path
# Phoenix 1.4
Routes.static_path
Now that these are out we should make the necessary changes to the project to bring it up to speed. Any help would be greatly appreciated ๐
I've gone ahead and done this.
Here's what is should look like (exact match for 1.4)
doctype html
html lang="en"
head
meta charset="utf-8"
meta content="IE=edge" http-equiv="X-UA-Compatible"
meta content="width=device-width, initial-scale=1" name="viewport"
title Hello Teacher!
link rel="stylesheet" href="#{ Routes.static_path(@conn, "/css/app.css") }"
body
header
section.container
nav role="navigation"
ul
li
a href="http://www.phoenixframework.org/docs" Get Started
a.phx-logo
img src="#{ Routes.static_path(@conn, "/images/phoenix.png") }" alt="Phoenix Framework Logo"
main.container role="main"
p.alert.alert-info role="alert"= get_flash(@conn, :info)
p.alert.alert-danger role="alert"= get_flash(@conn, :error)
= render @view_module, @view_template, assigns
script src="#{ Routes.static_path(@conn, "/js/app.js") }"
EEx has a sigil for doing safe HTML in your Elixir code. At first look it doesn't seem to be too interesting, but with the new LiveView coming up, it looks pretty useful.
I hate writing Eex, love writing Slime. It'd be cool to be able to write slime in the live view, and it seems to me like a sigil for this is the first step in the right direction.
(Feature request)
a href="#{page_path(@conn, :index)}"
Generates the link as expected.
<a href="#{page_path(@conn, :index)}">
Causes the tag to be rendered out in plain text onto the page. In addition, ANY other tags or HTML style comments in the same block (indentation level) will not render correctly either.
Example:
p This is a test <a href="#{'test'}">Here's a link</a> <!-- and a comment --> <img src="and_a_picture.jpg" />
p <a href="#">this link works</a>
a href="#{'blah'}" and so does this one
p This is a test <a href="without">an elixir tag</a> <!-- embedded in the html -->
I'm a complete elixir/phoenix newbie, but my wild guess at why is that priv
needs to be added to the files section in the mix.exs package function.
mix phoenix.gen.html.slime Video videos user_id:references:users url:string title:string description:text
* creating web/controllers/video_controller.ex
* creating web/views/video_view.ex
** (CompileError) _build/dev/lib/phoenix/priv/templates/phoenix.gen.html/controller_test.exs:37: undefined function binary_id/0
(elixir) expanding macro: Kernel.if/2
_build/dev/lib/phoenix/priv/templates/phoenix.gen.html/controller_test.exs:37: (file)
(elixir) expanding macro: Kernel.<>/2
_build/dev/lib/phoenix/priv/templates/phoenix.gen.html/controller_test.exs:1: (file)
(elixir) expanding macro: Kernel.<>/2
_build/dev/lib/phoenix/priv/templates/phoenix.gen.html/controller_test.exs:1: (file)
(elixir) expanding macro: Kernel.<>/2
_build/dev/lib/phoenix/priv/templates/phoenix.gen.html/controller_test.exs:1: (file)
edit:
The new
template is incorrect and should use route_helper
instead of singular
(this is relevant when using the --web option).
Ignoring/breaking the Law of Demeter, having been exposed to #try
and the safe-navigation operator &.
in Ruby, I'm beginning to miss it in Elixir-land.
I posed a question in Elixir Forum, before realizing somebody had already asked the same question here: https://elixirforum.com/t/maybe-nil-protection-for-nested-structs/468
I'm wondering if you'd be okay supporting the solution suggested there: a Maybe
module with the function and macro.
In plain new project just created
I added into mix.exs
{:phoenix_slime, "~> 0.13.1"}
then
mix do deps.get, compile
Resolving Hex dependencies...
Dependency resolution completed:
...skip...
==> slime
Compiling 1 file (.erl)
Compiling 11 files (.ex)
warning: :slime_parser.parse/1 is undefined (module :slime_parser is not available or is yet to be defined)
lib/slime/parser.ex:12: Slime.Parser.parse/1
...skip...
== Compilation error in file lib/magazin_web/views/layout_view.ex ==
** (UndefinedFunctionError) function :slime_parser.parse/1 is undefined (module :slime_parser is not available)
:slime_parser.parse(<<100, 111, 99, 116, 121, 112, 101, 32, 104, 116, 109, 108, 10, 104, 116, 109, 108, 32, 108, 97, 110, 103, 61, 34, 101, 110, 34, 10, 14, 32, 32, 104, 101, 97, 100, 10, 14, 32, 32, 32, 32, 109, 101, 116, 97, 32, 99, 104, 97, 114, ...>>)
lib/slime/parser.ex:12: Slime.Parser.parse/1
lib/slime/renderer.ex:17: Slime.Renderer.precompile/1
lib/phoenix_slime/engine.ex:9: PhoenixSlime.Engine.compile/2
(phoenix 1.5.3) lib/phoenix/template.ex:351: Phoenix.Template.compile/3
(phoenix 1.5.3) lib/phoenix/template.ex:166: anonymous fn/4 in Phoenix.Template."MACRO-__before_compile__"/2
(elixir 1.10.3) lib/enum.ex:2111: Enum."-reduce/3-lists^foldl/2-0-"/3
(phoenix 1.5.3) expanding macro: Phoenix.Template.__before_compile__/1
lib/magazin_web/views/layout_view.ex:1: MagazinWeb.LayoutView (module)
(elixir 1.10.3) lib/kernel/parallel_compiler.ex:304: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/7
Erlang/OTP 22 [erts-10.7.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]
Elixir 1.10.3 (compiled with Erlang/OTP 22)
Hello,
I'm seeing an UndefinedFunctionError when running
mix phoenix.gen.layout.slime
in an umbrella app in Phoenix 1.3 RC3. I'm using PhoenixSlime 0.9.0. Here is the output:
`** (UndefinedFunctionError) function Mix.Phoenix.copy_from/5 is undefined or private. Did you mean one of:
* copy_from/4
Mix.Phoenix.copy_from([".", :phoenix_slime], "priv/templates/phoenix.gen.layout.slime", "", [application_module: "ApplicationName"], [{:eex, "app.html.eex", "web/templates/layout/app.html.slim"}])
lib/mix/tasks/phoenix.gen.layout.slime.ex:16: Mix.Tasks.Phoenix.Gen.Layout.Slime.run/1
(mix) lib/mix/task.ex:301: Mix.Task.run_task/3
(mix) lib/mix/cli.ex:75: Mix.CLI.run_task/2
(elixir) lib/code.ex:376: Code.require_file/2`
This is happening in a new Phoenix umbrella app, which was generated via the following command:
mix phx.new portal --umbrella
The only thing I've changed from the default configuration is adding PhoenixSlime to the project. Please let me know if you need any further information.
Right now parts of the HTML output from Slime are long lines of tags.
It would be nice to have a configurable option to have formatted output.
Versions:
phoenix_slime 0.9.0
Elixir 1.5.1
Phoenix 1.3-rc
Slime:
a href="#{@slice.href}"
.promo-container class="promo-container--#{@side}"
Output:
<a href="https://staging.therealreal.com/consign"></a>
<div class="promo-container promo-container--left">
In addition to serving as an example for those looking to use PhoenixSlim, it'll provide a platform to reproduce bugs from scenarios that may not occur in my active projects (see #7).
PhoenixSlime ?
Master is already compatible so can you create a new release so I can upgrade my dependencies?
https://github.com/slime-lang/slime picked up support for Tailwind CSS recently by supporting colons and slashes in class names, see:
Phoenix slime would do well to pick this up as well.
For reference, here's the commit against slim that adds such support:
It works if the file exist when the server starts, but when I create a new file I have to restart the server.
With Phoenix 1.5.0 release, the generated app offers default configuration in scaffold for live_view. A default phoenix app with the --live flag now generates a different layout set than the current (at the time of this issue, v 0.13.1) phoenix_slime. Phoenix now uses a root, app, and live layout templates.
After manually converting over the generated layout files, and proving those to be functional, converting the inner generated content (App.PageLive.html.leex) results in an error. Build prior to transforming template to slimleex gets re-used, so have to delete build file and rebuild to produce the error, otherwise appears to fail silently.
render/1 was not implemented for PhxslimeWeb.PageLive.
Make sure to either explicitly define a render/1 clause with a LiveView template:
def render(assigns) do
~L"""
...
"""
end
Or create a file at "lib/phxslime_web/live/page_live.html.leex" with the LiveView template.
In the call to Phoenix.LiveView.renderer, the block generating the error:
defmodule Phoenix.LiveView.Renderer do
@moduledoc false
defmacro __before_compile__(env) do
render? = Module.defines?(env.module, {:render, 1})
template = template_path(env)
case {render?, File.regular?(template)} do
{true, true} ->
IO.warn(
"ignoring template #{inspect(template)} because the LiveView " <>
"#{inspect(env.module)} defines a render/1 function",
Macro.Env.stacktrace(env)
)
:ok
{true, false} ->
:ok
{false, true} ->
ast = Phoenix.LiveView.Engine.compile(template, template_filename(env))
quote do
@file unquote(template)
@external_resource unquote(template)
def render(var!(assigns)) do
unquote(ast)
end
end
{false, false} ->
message = ~s'''
render/1 was not implemented for #{inspect(env.module)}.
Make sure to either explicitly define a render/1 clause with a LiveView template:
def render(assigns) do
~L"""
...
"""
end
Or create a file at #{inspect(template)} with the LiveView template.
'''
IO.warn(message, Macro.Env.stacktrace(env))
quote do
def render(_assigns) do
raise unquote(message)
end
end
end
end
In the {false, false} case, the view's render function is not defined and File.regular? returns false.
Elixir v 1.10.2; Phoenix v 1.5.0
Github Repo project: https://github.com/CatsOnFilm/phxslime
Not sure if this is a slime issue. Trying to render a partial, following the book "programming phoenix":
= render "_user.html", user: user
Gives me an error:
Could not render '_user.html' for Rumbl.UserView, please define a matching clause for render/2 or define a template at "web/templates/user". The following templates were compiled:
* _user.html
* index.html
* show.html
Funnily it says the template is _user.html is compiled, so what's going on?
Failed to use "phoenix" (version 1.3.0-rc.0) because
phoenix_slime (version 0.8.0) requires ~> 1.2 *
mix.exs specifies ~> 1.3.0-rc
If I can manage to find the time tomorrow, I'll make a PR. I guess we should just update the mix file and the readme paths. Maybe the generator too, I'll check that.
With LiveView coming on the scene, Slime's use of sigils could stand a review. Specifically, I see two issues that may warrant attention:
Slime's use of ~l
and ~L
as inline content sigils conflict with LiveView sigils of the same name. Being as LiveView is likely sticking around, it stands to reason that this conflict should be resolved before there's too much precedent. Note that while one can sidestep this by selectively importing LiveView (import Phoenix.LiveView.Helpers, except: [sigil_L: 2]
is what I'm using), it's one more step to integrate, and as such it may be worth tearing the band-aid off early on this.
Slime lacks a set of sigils for inline LiveView, which would be quite handy as LiveView patterns tend to prefer inline markup. (Note that the actual implementation of such a sigil looks pretty straightforward based on reviewing how the LiveView project does it).
To stimulate discussion on this, I'd like to propose three options:
Double down on Slime as a replacement for EEx and start using ~e
/ ~E
for non-live slime, and ~l
/ ~L
for live-slime. This has the downside of not coexisting at all with EEx's sigils, but also the upside of being pretty explicit (and clear to switch between based on selective imports of one or the other as above).
Do our best to accommodate LiveView (on the premise that it's only going to get more popular over time) and update Slime's sigils to something other than ~l
/ ~L
. I might suggest using ~i
and ~I
for non-live slime, and ~m
and ~M
for live slime (since those are the next characters in the word 'slime'), but that's just an idea.
Keep the status quo and update documentation as appropriate. Either pick another character for a live-slime sigil, or use a trailing modifier on the existing sigil to indicate live-ness (side note: it's annoying that LiveView didn't do this, though understandable given that it's a distinction that spans two libraries).
I'm quite happy to work up a PR to implement any of the above ideas, but I'd like to solicit community feedback on them before proceeding (FWIW, I think I prefer option 1 but I'll admit to not having thought it through super deeply).
Hi there,
I'd like to humbly ask whether you could upload a new version of this library to mix
please? Version 0.12.0
is from Dec 2018
and does not include LiveViewEngine. A new version including all the changes since Dec 2018 would be nice to have (for a CI without git dependencies for example)
Much appreciated!
Just updated the latest LiveView from Github
Failed to use "phoenix" (version 1.4.4) because
deps/phoenix_live_view/mix.exs requires ~> 1.4.8
deps/phoenix_slime/mix.exs requires ~> 1.4
mix.lock specifies 1.4.4
When I try to use the slime html generator
mix phoenix.gen.html.slime Account accounts name:string bank:string
I get the following error message:
** (CompileError) _build/dev/lib/phoenix/priv/templates/phoenix.gen.html/controller_test.exs:37: undefined function binary_id/0
(elixir) expanding macro: Kernel.if/2
I am using phoenix
1.1.4 with phoenix_slime
0.0.6.
If I use the phoenix generator it works.
Any idea why?
link rel="stylesheet", href="#{static_path(@conn, "/css/app.css")}"
vs
link[rel="stylesheet", href="#{static_path(@conn, "/css/app.css")}"]
vs
link(rel="stylesheet", href="#{static_path(@conn, "/css/app.css")}")
The first and second examples work, the third fails with: ** (TokenMissingError) lib/foo/web/templates/layout/app.html.slim:26: missing terminator: "
Typically all of my liveviews have an explicit render
, as in:
def render(assigns) do
MyappWeb.SomeView.render("index.html", assigns)
end
Recently I tried out the mix phx.gen.live
scaffolding, which uses the new "impicit" render, i.e there's no "render" function in the liveview, and the template lives next to the liveview in /myapp_web/live/...
.
When rendering a template that was generated this way, the extension I specified is ignored, even though I have the file named properly.
Is it possible that the new implicit view module stuff in liveview isn't aware of the engine declaration? Apologies if this isn't terribly clear.
Running test with a slim template fails with a Diff.many_to_iodata/5
error:
** (FunctionClauseError) no function clause matching in Phoenix.LiveView.Diff.many_to_iodata/5
(phoenix_live_view 0.15.4) lib/phoenix_live_view/diff.ex:74: Phoenix.LiveView.Diff.many_to_iodata(["", ""], [], ["media-1", " "], %{}, #Function<13.114466470/2 in Phoenix.LiveViewTest.DOM.render_diff/1>)
The exact same template converted in eex does not fail.
You can reproduce the error with the following repo: https://github.com/rlecostey/liveview_diff_issue
mix test
runs two tests: one with eex template and another with the slim template, only the latest triggers the error
I tried debugging within Phoenix.LiveView.Diff
but I had a hard time figuring out how exactly this is working ๐
Thanks for your help!
(already opened and closed here: phoenixframework/phoenix_live_view#1391)
I'm trying to use Slime templates in Bamboo and here is what I get. I suppose that render_to_string
expects a binary, not a safe string. Phoenix.Template.EExEngine
works fine here.
Request: POST /lead/join
** (exit) an exception was raised:
** (ArgumentError) argument error
:erlang.iolist_to_binary({:safe, ["" | "a"]})
(phoenix) lib/phoenix/view.ex:342: Phoenix.View.render_to_string/3
(bamboo) lib/bamboo/phoenix.ex:247: Bamboo.Phoenix.render_html_and_text_emails/1
Any plans on pushing a new hex release with the latest changes?
Hello!
I have a strange trouble with using gettext
in slime templates. I tried to do something like this:
span title=gettext("Text")
and this works fine, but when I try to do the same but with whitespaces in gettext:
span title=gettext("Text with whitespaces")
I got an error:
missing terminator: " (for string starting at line 1)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.