Comments (53)
calliope is coming along nicely. I can actually parse basic haml structures now and looking to have scripting done this week (fingers crossed).
from phoenix.
Exciting! 95% of the markup I write is haml so I can't wait for this.
from phoenix.
It's making our designers really happy too :)
from phoenix.
Thought you might like to see these:
Calliope is almost there so I wanted to see how hard it would be to add in. Feedback is appreciated :)
from phoenix.
Oh this is awesome! I can't wait to try this out. Any thoughts to how to handle runtime rendering? Are you planning on rendering flat .haml files or can we work in some kind of precompile mechanism that compiles the haml into the application for later rendering?
from phoenix.
I just got done testing in an actual browser and everything renders perfectly. I wanted to get a first pass at an integration to see what works best. As you can see that was actually pretty trivial.
Calliope's render takes a string of haml and the arguments needed to compile the flat html. It seems like passing the file at runtime would be the best option. Plus, having calliope expect anything other than a haml string and arguments, seems too coupled to an implementation. In this case, Phoenix can decide the when, how, & from where the haml comes from and then pass it along to be rendered. My thought is the haml
function would use __MODULE__
to determine a folder and the atom passed in would be a file. If a string is passed, the function would assume a string of haml and just pass it on(?).
from phoenix.
@nurugger07 nice! Regarding XSS, colliope is making this easier to handle than EEx at the moment? I am kind of lost on XSS atm :)
Having haml/eex compiled could give serious speed improvements, of course in that case haml file discovery could not be done at runtime. In that case we would probably need whole new layer that compiles haml/eex, and eex
, haml
functions would need to grab it from some template index.
from phoenix.
I would recommend to take a look at Dynamo / Chicago Boss. For development, we compile the templates into a fake module (Dynamo.Templates1) and dispatch to and reload those modules at will. For production, we compile everything into Dynamo.CompiledTemplates
and simply have an entry point in the module.
Any solution that is not based on compilation will be very slow, given that eval in Elixir is slow.
from phoenix.
@josevalim Thanks, I'll take a look at how they are handling this. My first goal to get something working and see it deliver html to the browser correctly :) If you get a chance to look at the calliope code I'd appreciate some thoughts/feedback. You can email me directly or through that repo.
from phoenix.
Not sure if this would be desired or not, but I've been working on a general helper library for template engines. It currently supports ErlyDTL (used by ChicagoBoss) and HAML via @nurugger07's Calliope with plans to add in EEx soon. Allowing multiple types of templates could aid in adoption of Phoenix, where developers could bring over existing templates without having to start from scratch.
End goal of the project is to allow web applications to use any supported templates, using pre-compilation to help speed up the rendering process.
It's very much a work in progress, with quite a bit of work left including configuration and a defined API, but both ErlyDTL (compiled on first use) and Calliope (no compilation) engines return HTML when called directly. Take a look at the project at slogsdon/templates, and let me know what you think.
from phoenix.
Awesome! I'll take a look. One thing we need to be careful of is proper xss protection, and pre-compilation with whatever template engine is supported. EEx as implemented cannot properly protect against xss, but there are discussions currently on how we can get it in place. We also can't rely on Code.eval_string
in production for reliable performance. https://github.com/zambal/eml is also worth a look. I agree a general helper library would be extremely nice that we could leverage across different engines.
from phoenix.
@chrismccord Agreed re: xss and eval
ing. I'll take a look into eml. It looks like a nice option.
from phoenix.
The templates project is a good initiative! I believe that whatever approach we choose needs to support explicit pre-compilation though (and not on demand like ErlyDTL) because when you build a release all the code is loaded upfront (the virtual machine does not load code dynamically).
A couple feedback regarding templates:
- I would suggest to leave Templates.Finder out of it (it is almost always framework specific);
- Have the source in the template and get rid of filename (templates should be able to come from the database, for example). Advise handler implementations to get rid of the source after compilation (and keep the source if they need it at runtime, like calliope);
- Get
compile/1
to return the beam source (gives you more flexibility to where to put the beam source later); - Make the key an atom (it is very likely that's how the majority of templates will use it);
from phoenix.
@josevalim Thanks for the advice! Pre-compilation is definitely a goal, and the benefits of it are entirely understood. The current ErlyDTL implementation was a test run to make sure I was headed in the right direction.
from phoenix.
You definitely are. The template engine api you have is similar to the ones in chicago boss and dynamo.
from phoenix.
Glad I saw this :) I was debating on adding a template engine to calliope. I'm trying to work on integrating calliope with phoenix to test performance.
from phoenix.
Ok, since many people working with web frameworks are in this thread, I would like to suggest a structure to avoid XSS attacks that would definitely work with EEx. It is very likely to work with Calliope too (please confirm).
The problem with EEx is that it interpolates strings. And, in a regular string, we don't know if the contents are safe or not. The idea here is to come up with a more structured way to represent HTML nodes in Elixir. Basically, a node can be represented as:
@type html_node :: {tag :: atom, attributes :: Keyword.t, [html_node]} | String.t
When the node is a tuple, it represents an html tag and the contents are expected to be html safe. I.e. they won't be escaped. Strings are considered to be raw and will always be escaped.
This is nice because creating tags can be done as:
{:a, [href: "/"], ["Home"]}
And the engine will translate that to the proper HTML representation.
What do you think?
So far I can think of only one (solvable) issue in the proposal above: there is no way to represent a HTML safe string without wrapping it in a tag and that may not always be desired. People may also want to concatenate two nodes (a tuple one and a string) without wrapping it in a tag. This means we need a third representation that can have many elements without generating a tag. We have two options:
-
Use the
{tag, attributes, body}
structure but have a special tag name for it. For example, the tag name could be:group
or:safe
. The issue with this approach is that the attributes will never be used and if HTML adds a :group tag, we are screwed. :) -
We could use a
{:safe, body }
tag. It has a different structure, that reflects the lack of a tag. The updated node would be:@type html_node :: {tag :: atom, attributes :: Keyword.t, [html_node]} | {:safe, [html_node]} | String.t
The only downside of this approach is that code that traverses the tree now needs to traverse three different structures, but most of this work will likely be done by functions anyway.
Thoughts? /cc @ericmj @devinus
from phoenix.
@josevalim calliope parses the haml/elixir into a structure like prior to being compiled:
[ line_number: 1, tag: "h1", content: "Calliope" ],
[ line_number: 2, tag: "div", children: [
[ line_number: 3, indent: 1, script: "subtitle" ]]],
[ line_number: 4, smart_script: "lc {id, content} inlist posts do", children: [
[ line_number: 5, indent: 1, tag: "div", classes: ["row"] children: [
[ line_number: 6, indent: 2, tag: "a", attributes: "href='posts/'\#{id}'", content: "'\#{content}"]]]]
Finally, the nested structure is compiled into html and that is the point when the elixir is evaluated. Currently, strings are being interpolated but the "smart_scripts" are being constructed and run through string_to_quoted
before being passed to eval_quoted
. (Is there any advantage in this?)
I just added a validation function that could "scrub" scripts. It runs before the nesting and compilation. I'll look at implementing an html_safe
function to run around interpolated content.
If anyone has thoughts or ideas for this, I'd greatly appreciate it.
from phoenix.
Notes from a discussion I had with @josevalim:
An HTMLSafeEngine
for EEx could simply escape by default but expect String.t | { :safe, [html_node] }
for the vars. Helper functions would generate { :safe, [html_node] }
which the engine could then traverse, build the HTML strings and insert unescaped.
from phoenix.
I've been working this into calliope. I have a separate module to handle
evaluating and escaping. By default, args passed to the template are made
HTML safe prior to the code being evaluated so this:
render "%h1= title", [title: "<script>a bad script</script>"]
would render:
<script&rt;a bad script</script&rt;
However, you could prevent the default behavior by doing the following:
render "%h1= Safe.script(title)", [title: "<script>a good script</script>"]
and that would render:
<script>a good script</script>
You can also use the Calliope.Safe.clean/1 from Elixir to scrub any string.
Here is a link to the branch if you want to check it out but keep in mind
it's not complete:
https://github.com/nurugger07/calliope/blob/html_safe/lib/calliope/safe.ex
and tests:
https://github.com/nurugger07/calliope/blob/html_safe/test/calliope/safe_test.exs
from phoenix.
@nurugger07 Nice! How do you know if a value was already escaped?
from phoenix.
@josevalim for now, I don't and I assume values need to be escaped unless it has been designated as a safe script. This should suffice in most cases but eventually it will need to be smarter. The nice thing is it's abstracted into its own module so modifications should be isolated. I was debating making Safe a small library but still haven't decided.
I need to address rendering partials today because I know @knewter is compiling the haml and passing it in as an argument. Which should be fine if he wraps the args in Safe.script
but really this is the job of a render_partial
function.
from phoenix.
@nurugger07 from what I understand, Safe.script
exists only in HAML, which means it is very hard to write helpers/functions that receive possibly safe strings and emit possibly safe or unsafe strings. This means writing helpers like link_to
, my_menu_link
become quite hard or you need to declare something as safe multiple times, no?
from phoenix.
@josevalim for now, yes. Safe.script
bypasses the argument checks. There is a Safe.clean
function that works outside of HAML to "clean" strings/lists. I tried to implement a solution that would work for now but I could refactor later with new features.
What do you think of these helpers?
Arguments are cleaned:
= link_to "#{subject}", "/posts/#{id}"
Arguments are not cleaned:
= safe_link_to "#{subject}", "/posts/#{id}"
= my_custom_link_to(subject, id)
def my_custom_link_to(text, id) do
"<a href='/posts/#{Safe.clean(id)}'>#{Safe.clean(text)}</a>"
end
I'm working on a project that I'll be demoing at Erlang Factory that provides a "real-world" application to test out the implementations. That will help drive a better long term solution. I'm open to any ideas or contributions :)
Regarding the pre-compiling, I was thinking about working on the template engine to index and compile the scripts to increase performance. I would create a function at compile time that takes the arg as a parameter and returns the result. I would just replace the script with a generated name. Also, appreciate thoughts on this :)
from phoenix.
What do you think of these helpers?
Sorry, I couldn't see the difference in between the arguments being cleaned and not being cleaned. Do you mean link_to
is somehow special cased and my_custom_link_to
is not?
from phoenix.
Sorry I meant to say = safe_link_to
. Copy & paste error :/
from phoenix.
My thought was that there would be built in helpers that would safely escape args but then there would be "safe" helpers that the args wouldn't be escaped. Custom helpers would also assume that devs are escaping the html.
That being said, I could be totally wrong in that line of thinking :)
from phoenix.
Custom helpers would also assume that devs are escaping the html.
That's a very dangerous assumption to make even more if you consider that helpers are just functions. If you have more strict rules about creating and adding helpers, maybe that would work, but it is still is the opposite of what you'd want to do.
I would rather assume that nothing is safe and ask users to explicitly mark what is safe. But even an approach like that is tricky. If you need to explicitly mark even basic functions like link_to
as safe, people would just end up marking all functions as safe, because if they don't, their code would appear escaped.
That's why I was thinking of a more explicit tagging approach. We don't assume anything is safe, we rather ask the function to return something that is safe or not. And link_to could return something safe by default, which means it works pretty much out of the box.
The nice thing about using explicit tags is that they could be used by any engine. The API is actually rather simple:
defmodule HTMLSafe do
@type t :: safe | unsafe
@type safe :: {:safe, String.t}
@type unsafe :: String.t
@spec safe(t) :: safe
def safe({:safe, _} = safe), do: safe
def safe(string) when is_binary(string), do: {:safe, escape(string)}
@spec concat(unsafe, unsafe) :: unsafe
@spec concat(t, t) :: safe
def concat({:safe, s1}, {:safe, s2}), do: {:safe, s1 <> s2}
def concat(s1, s2) when is_binary(s1) and is_binary(s2), do: s1 <> s2
def concat(s1, s2), do: concat(escape(s1), escape(s2))
end
I have originally proposed representing the HTML nodes as tree structures as well which would lead to a slightly more complex implementation but it comes with the nice side-effect that you would actually be able to traverse HTML code as data.
from phoenix.
Regarding the pre-compiling, I was thinking about working on the template engine to index and compile the scripts to increase performance.
For precompilation, I believe you should just emit quoted expressions. Take a look at the EEx main functions (function from file, function from string and so on). For example, in EEx, when you write:
foo
<%= :bar %>
baz
It literally compiles to (represented as quoted expressions):
"foo\n" <> to_string(:bar) <> "\nbaz\n"
This way, you can just inject this code into an elixir function and elixir does the job of optimizing what it can out of it.
from phoenix.
π but I would make concat make IO lists.
from phoenix.
@devinus What is the benefit we would get out of it? If we start inserting io lists in the user code (which concat/2
is definitely part of), it means our types now become:
@type t :: String.t | iolist
And that is just asking for massive headaches. Now you can't even extract something out of it and call downcase on it.
If we represent HTML tags as nodes, then the underlying template engine could convert them to iolists instead of binaries, but that should only be done internally. But even though we need to do benchmarks to see if there is some real benefit. I definitely do not think it should be part of the user concern.
So the questions are:
- Do we want to represent HTML nodes as tuples? For example,
link_to/2
would return{:a, [href: target], [text]}
instead of"<a href=#{inspect target}>#{text}</a>"
; - If so, can template engines like Calliope and EEx get a nice performance out of it by compiling them to iolists?
from phoenix.
@chrismccord @josevalim I took a stab at ripping out whats currently view wise in dynamo and adapt it to phoenix. It's basically a copy/paste of the current dynamo view layer with adjustments from dynamo/connection to plug/connection functionality.
You can take a look at it here: https://github.com/BjRo/phoenix/compare/dynamo_view_layer
Please note that there're right now no tests for that. I just wanted to see how far I can get, porting a dynamo side project over to phoenix. I'm able to render a pretty complex view with lots of partials with that code which is nice so far.
To give you a bit background on the why. My current employer is so nice to give us time to work on innovation projects every 8 weeks. The last time around I and 2 colleagues wrote a small stackoverflow clone with (guess what :-)) dynamo and I'm currently trying to port over what we have to phoenix.
Judging from the discussion so far, it's probably not 100% what you would like to have for phoenix, but it enables my project to move our code over to phoenix for the moment (until there's a full blown solution in phoenix for that).
Thoughts?
from phoenix.
@BjRo wouldn't it be best to extract those view modules into a project on its own which can be used by Dynamo and Phoenix? Or are they too tightly coupled to other framework modules?
from phoenix.
The view engine I'm working on for calliope is easy to add to any library and should work with Phoenix or Dynamo with very little effort.
from phoenix.
@patrickdet Yes, probably. To be honest though, it was an intermediate step for us that allows us to switch to phoenix. In the long run, we definitely want to switch to @nurugger07's calliope for our views. That's why I'm a bit shy to invest a lot of time there :-)
from phoenix.
@nurugger07 did you finally settle on any internal implementation for safe html chunks in calliope?
from phoenix.
@josevalim yes and no. So there were a couple of issues I was trying to address and figured the best way was to break it up. The first thing I did was to change the output of to be an eex formatted string for compile time and then I utilize EEx if you want to compile the template at runtime.
require EEx
def render(haml, args \\ []) do
precompile(haml) |> eval(args)
end
def precompile(haml) do
tokenize(haml) |> parse |> compile
end
defp eval(html, []), do: html
defp eval(html, args), do: EEx.eval_string(html, args)
Now I'm focusing on a view engine to read the haml templates in and compile them into named functions. I lose XSS support because of EEx but I'm going to circle back around and address it. I may look at a solution for EEx if that's ok and then leverage it in calliope.
I punted mainly because I want calliope to output an Elixir AST but I know people are waiting on compiled templates. I figure putting in a public api that allows me to abstract the internals will make it easier to transition later. Plus, I can depend on everyone having EEx :)
from phoenix.
Ok, if I understood it correct: you are currently outputting an EEx string because you can compile it but in the future you want to output Elixir AST directly, which then allows you to skip EEx altogether, right?
from phoenix.
That's the plan today but I'm not entirely sure it's necessary. If I can work XSS support into EEx is there much benefit in skipping it?
from phoenix.
@nurugger07 if you are going to generate Elixir AST from calliope then there is no need to use EEx (unless you are using EEx to generate the Elixir AST). The compilation functions should be easy to port to Calliope once you have a function that receives a Calliope template and returns Elixir AST.
from phoenix.
So haml (at least originally) output erb files into an erb binding, which
led to a lot of occasional odd error messages. That might be one reason to
avoid taking roughly the same path? Compare this to slim, which I believe
actually implements its own bottom layer for the templating rather than
outputting erb templates.
On Wed, Mar 26, 2014 at 1:46 PM, Johnny Winn [email protected]:
That's the plan today but I'm not entirely sure it's necessary. If I can
work XSS support into EEx is there much benefit in skipping it?Reply to this email directly or view it on GitHubhttps://github.com//issues/11#issuecomment-38723746
.
Josh Adams
CTO | isotope|eleven http://www.isotope11.com
cell 215-3957
work 476-8671 x201
from phoenix.
I just wanted to say - I started looking into building a haml parser
yesterday with yecc, and ended up deciding that using a LALR(1) parser for
haml is possibly one of the dumber ideas I've had :) Still holding out
hope for a peg parser based on sean cribbs' neotoma.
On Wed, Mar 26, 2014 at 1:48 PM, JosΓ© Valim [email protected]:
@nurugger07 https://github.com/nurugger07 if you are going to generate
Elixir AST from calliope then there is no need to use EEx (unless you are
using EEx to generate the Elixir AST). The compilation functions should be
easy to port to Calliope once you have a function that receives a Calliope
template and returns Elixir AST.Reply to this email directly or view it on GitHubhttps://github.com//issues/11#issuecomment-38723917
.
Josh Adams
CTO | isotope|eleven http://www.isotope11.com
cell 215-3957
work 476-8671 x201
from phoenix.
The EEx solution is temporary and abstracted so it should be easy to remove the dependency without affecting consumers. I really just wanted a chance to get the templates compiled and kept going back and forth on how best to implement one. Using EEx is a short-term solution.
from phoenix.
@nurugger07 awesome! :)
from phoenix.
@josevalim I find that sometimes when I punt on things and circle back around, I have a clear view :) Unfortunately, sometimes that's not an option.
from phoenix.
I'm experimenting with a precompiled/xss-safe Templating engine in cm-templates
branch:
https://github.com/phoenixframework/phoenix/tree/cm-templates
Big thanks to @ericmj for the EEx Html-safe engine.
What this branch gives you:
defmodule MyApp.Templates do
use Phoenix.Template.Compiler, path: Path.join([__DIR__, "templates"])
# This mod contains all templates and serves as base for view layer,i.e.:
def number_to_currency(number), do: ...
end
# Render from outside Controller, file : templates/show.html.eex
iex> MyApp.Templates.render("show.html", message: "Hello!")
"<h1>Hello!</h1>"
# Render from within Controller, file: templates/pages/home.html.eex,
# file extension picked based on request mime content-type
def show(conn) do
render conn, "pages/home", title: "Home"
end
# templates/layouts/application.html.eex automatically rendered with
# template as inner content, i.e.:
# <html>
# <title><%= @title %></title>
# <body>
# <%= @inner %>
# </body>
# </html>
# override with layout: false, or layout: "my_other_layout"
def show(conn) do
render conn, "pages/home", layout: false, title: "Home"
end
I'd like to see how we can take this and grow it to support other engines than EEx, i.e. @nurugger07 's Calliope.
Thoughts?
from phoenix.
Nice!
I really like how templates are compiled and clearly injected into the module. And I do have a couple questions:
-
Should we start worrying about how to compartmentalize the templates? The current implementation will embed all templates recursively but we probably want the users templates in a module, the posts templates in a module and so on. I am aware this is possible with the current implementation but what about subdirectories?
-
Is there a need to define functions (like render) in the template module? If not, I would avoid and instead do:
Phoenix.Template.render(MyTemplate, ..., ...)
. I usually define functions in a module are if they are one of:- When those functions are necessary for some behaviour (like a Plug needs to implement init & call, GenServer.Behaviour, etc)
- When we have a facade module (like MyRepo in Ecto.Repo)
- The functions exported are all metadata related (like
__templates__
)
The main reasoning is that injected functions are hard to document, test, etc.
-
Maybe we should make a distinction in between views and templates? View is the module where the template is rendered. The template is the file with the contents (usually EEx or Calliope). I am saying this because Rails calls views and templates the same thing, which is very confusing, and we end up needing to create names like view context and so on.
I have a couple notes regarding the implementation:
- There is a lot of work being done inside the functions defined via quote. It is always better for them to be simply a delegation to actual implementations
- It seems a controller can call a template and a template can call a controller functions. I would try to have the flow (the dependency) just one way (the controller calls the template and that is it. Maybe you will have to move common functions to the template).
from phoenix.
Thanks for the feedback @josevalim,
- This is something worth exploring. For large apps, we'll otherwise end up with,
render(conn, "admin/institutions/edit"...)
. A glance at the largest web apps I've worked on shows rarely more than 3 levels of view directories, but the controllers using the nesting might get tiresome. This might be heresy , but what if we used camel-cased template directories for the times we wanted a "submodule" and lowercase directories for times we wanted to simply nest the templates. Ie:
βββ Admin
βΒ Β βββ institutions
βΒ Β βΒ Β βββ _edit.html.eex
βΒ Β βΒ Β βββ new.html.eex
βββ Profiles
βΒ Β βββ new.html.eex
iex> MyApp.Views.Admin."institutions/edit.html"([])
iex> MyApp.Views.Profiles."new.html"([])
- I wasn't thrilled with
render
being inside the template, but couldn't think of a better way at the time to get the nice render/3 in the controller. I very much likePhoenix.Template.render(MyTemplate, ..., ...)
, and with the proposed namespacing of templates, it would let us:
defmodule MyApp.Controllers.Admin.Users do
use Phoenix.Controller
@views MyApp.Views.Admin
# render/3 imported from Phoenix.Views/Templates
def show(conn) do
render conn, @views, "users/show"
end
end
- I very much like the distinction of views/templates and I'm already having a hard time keeping the naming straight, likely because of Rails :). I think the base module that gets all the injected templates should be a "Views" module and will update the naming.
I wasn't thrilled with having to inject render
inside the template within a quote, but I couldn't figure out how to best get the controller rendering in place. #2 proposal will solve that by simply passing the view module in to an outside render func. This will also clean up the requirement of having to call the controller code from within the template. Thanks @josevalim , this has been really helpful feedback!
from phoenix.
This might be heresy , but what if we used camel-cased template directories for the times we wanted a "submodule" and lowercase directories for times we wanted to simply nest the templates.
I really like this! I like it because it makes it clear in the directory structure how it will be organized. It can also help us automatically get the template path without explicit configuration. One potential pain point though: what about shared templates?
MyApp.Views.Admin."institutions/edit.html"([])
I wouldn't invoke it like this though for a couple reasons:
- It means we will need to convert the template paths to atoms when rendering (and it could be lead to vulnerabilities due to atom injection)
- Maybe we need to know other information about the template. For example, ask if the template exists before rendering it or its format (although the format can be extracted from its name).
Just to be clear, it is fine if we keep it as render(name, assigns)
as long as it is not coupled to the connection and this is specifically marked as the template API. If we do this though, we will need another function to return the template metadata (maybe __template__(path)
).
π I really like the direction this is going (and it is one of the things I didn't like and was too hacky in Dynamo).
from phoenix.
A slight off-topic: in JS community there's this new thing being developed called HTMLBars. It uses Handlebars' template language, but compiles into a DOM tree instead of a string.
@josevalim has proposed doing something similar with EEx, so I'm posting this just as something to keep an eye on to see how it turns out in terms of usefulness and community response.
from phoenix.
Hey people.
I have put up the view engine I'm working on β https://github.com/alco/wyvern. The implementation is very much a WIP, but I've put considerable effort into describing the project's purpose and usage in the README. You can also consult the tests for usage examples, they all pass.
Regarding the usefulness of this project, I'm going to work on the compiled aspect and caching next.
Compiled views will just be modules corresponding to views in your app. If you have an "index" view that is based on the "base" layout and also has a navbar, you should be able to have modules for all these stagesβbase layout, navbar, index viewβso that at run time no time is spent on parsing the templates; it will be purely rendering.
Alternatively, you can have a module only for "index" and compiled the other layers right into it (it works like that right now).
The idea for caching I have in mind is that it'll be useful for different use-cases: both compiling views into static files hosted on CDN as well as serving views dynamically. See README for more.
The current impl is tied to EEx, but I'm planning to make this thing as flexible as possible. Things like escaping HTML and supporting other templating languages are on my TODO list.
I will appreciate every bit of positive and negative feedback you may want to throw at me.
from phoenix.
@alco calliope has precompiled templates built into the view engine too. I'm currently just testing the implementation in a couple of projects to look for issues. I offer compiled or runtime options for parsing the haml templates.
from phoenix.
@nurugger07 Great! I'll give it a try.
from phoenix.
Related Issues (20)
- Incorrect parameter name for category IDs in "Contexts" guide section HOT 2
- multiple phx.digest in mix alias doesn't work HOT 1
- Hard to spot when phoenix application conflicts with a dependency. HOT 1
- Stale moduledoc for `Token` regarding token secrecy HOT 2
- weird behaviour when deep merging endpoint options HOT 1
- `Phoenix.Presence.get_by_key/2` typespec, return values, and documentation are inconsistent HOT 2
- Hexdocs.pm are missing the core_components.ex HOT 1
- Weird debug output on fresh project HOT 2
- Ecto.NoResultsError not swallowed HOT 10
- HTML and Live CRUD generators output invalid HTML (buttons nested in links)
- I would like to request `Phoenix.Endpoint.init/2` callback not be deprecated HOT 2
- Modules with dependencies using fetch_env are not recompiled in dev. HOT 4
- Updating tailwind css to 3.4.x for phoenix 1.7.x (default) HOT 1
- Current approach to passing token in channels is unsafe
- In Phoenix JS, removing one never-joined Channel removes all never-joined Channels HOT 2
- Swoosh crashes if phx.new.ecto does not get run with --no-mailer HOT 1
- Using `mix phx.new` with `--no-html` still configures live_view in test config HOT 2
- assert_push & al. badly expands its arguments
- Phoenix app has issues with debugging unit tests HOT 1
- Default :info flash is not an Info flash, it is a Success flash
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from phoenix.