Riot: Custom text in tag

Created on 27 Nov 2015  Â·  38Comments  Â·  Source: riot/riot

Hi I recently upgraded to 2.3.11 and I found that I get some bad looking compiled tags in situations where the content is interpolated text without an outer tag. Eg.

<x>
    {opts.text}
</x>

is compiled to

riot.tag2('x', '', '', '', function(opts) {
    {opts.text}

});

Am I doing something wrong ?

bug discussion

Most helpful comment

Well I'm not sure that you'll agree with me, but I've never particularly
liked the magic guessing of JS. Whilst clever, it seems brittle and
unnecessary. I always use a

All 38 comments

I think the new compiler does not work with this kind of custom tags probably because it's a tag without any template. But I guess it should be fixed. @aMarCruz Can you have a look please?

@GianlucaGuarini , sure. I'll take a look.
Seems related to this issue

@weepy , @GianlucaGuarini , I really don't know if we must support this construction.

From the riot guide here:

Without the <script> tag the JavaScript starts where the last HTML tag ends.

From riot-compiler guide here:

In the remaining content, looks for the last html tag which ends a line. If found, this closing tag signals the end of the html markup and the beginning of the JavaScript code. If not found, all remaining is considered JavaScript.

How to differentiate html from JS without the html tags? think about:

<x>
  what_i_am()
</x>

I think the whole <x> is html, but in the riot context its content is JS.
What do you think?

Well I'm not sure that you'll agree with me, but I've never particularly
liked the magic guessing of JS. Whilst clever, it seems brittle and
unnecessary. I always use a

So its just a hack. Virtual tags would be removed leaving only their
content.

On Fri, 27 Nov 2015 20:28 Alberto Martínez [email protected] wrote:

I agree, and untagged js complicates the parsing.
Assuming remaining content as html seems more intuitive, but this would be
a breaking change.

What do you mean with tags?

—
Reply to this email directly or view it on GitHub
https://github.com/riot/riot/issues/1387#issuecomment-160200470.

I got it, with these we can fix the <option> in mixins problem too:

<select riot-temp><option></select>

I don't like this solution for the untagged html issue here, but maybe we can implement it.
Let's wait for @GianlucaGuarini , it needs a change in the riot core.

@tipiirai , @cognitom , @rsbondi , @GianlucaGuarini ,
we must consider untagged content as html?
what do you think about virtual tag containers?

for @weepy I think your tag probably does not even need to be compiled I achieved the same result with 3 lines of js http://plnkr.co/edit/hCjfmsM2w5RDNjVMAtZk?p=preview I would not overcomplicate the core for features that can be done outside the framework. Something cool can be an extension library with special tags and mixins that we can host/maintain in our riot organization

Sure there's hacks around it. Just seems a very basic use case. It will
bite a lot of people so the very least it should be documented.

On Fri, 27 Nov 2015 23:15 Gianluca Guarini [email protected] wrote:

for @weepy https://github.com/weepy I think your tag probably does not
even need to be compiled I achieved the same result with 3 lines of js
http://plnkr.co/edit/hCjfmsM2w5RDNjVMAtZk?p=preview I would not
overcomplicate the core for features that can be done outside the
framework. Something cool can be an extension library with special tags and
mixins that we can host/maintain in our riot organization

—
Reply to this email directly or view it on GitHub
https://github.com/riot/riot/issues/1387#issuecomment-160226239.

@weepy So we can add to the documentation something like:
Custom tags not containing any html template can not be properly compiled. For example:

<coordinates>
  { x } - { y }
</coordinates>

In this case you may simply use:

riot.tag('coordinates', '{ x } - { y }', function() { })

@aMarCruz what do you think?

@GianlucaGuarini , to make the @weepy example work, it is needed change ['', str] to [str, ''] in this line, but it is a breaking change, so I will update the docs.

I don't like at all because it implies that there are forms that can not be used. e.g.

<p riot-tag="foo">Hi</p>

while we can always include JS through the <script> tag.

Just throwing in my two cents... I've always used the script tags for similar reasons as @weepy. It seems weird that you can't do this.

<x>{ opts.text }</x>

the breaking change can be less harmful if we require the enclosing <script> only for tags that are not wrapped in a container, and make it optional/suggested for the other cases. That would make 90% of the code out there still work.

@nippur72 , that results in the same.

@aMarCruz yes still a breaking change, but it's better than forcing people to use <script> all the time.

Anyway, I put my +1 on the breaking change, I value more to be able to write tags like <x>{any}</x> than preserving retro-compatibilty. The breaking change is easy to fix, so it isn't a real problem even if you have a large code base.

@nippur72 , I agree with you, with the consensus of the team I hope that this change can be done.

I've never used it without <script> inside the tag definition... I prefer the idea "always <script>". But I guess @tipiirai likes the "loose" mode? cf. https://github.com/riot/riot/issues/794#issuecomment-110095367

@weepy another hack could be like this:

<x>
    this.root.innerHTML = opts.text
</x>

http://plnkr.co/edit/uwJ2lmkgPOsSAejKLQFU?p=preview

Yes @tipiiari argues that riot strives for minimal boilerplate and it's easy to detect the difference between JS and HTML.

To which I would quote Einstein : "Everything should be made as simple as possible, but not simpler."

^_^

BTW, I'm not sure it was already mentioned or not, the code below works. But only if it is written in one line :-)

<x>{ opts.text }</x>

http://plnkr.co/edit/PcsGADcbVKIaADOdaQ8t?p=preview

Why's that ?

On Tue, Dec 1, 2015 at 7:57 AM Tsutomu Kawamura [email protected]
wrote:

BTW, I'm not sure it was already mentioned or not, the code below works.
But only if it is written in one line :-)

{ opts.text }

http://plnkr.co/edit/PcsGADcbVKIaADOdaQ8t?p=preview

—
Reply to this email directly or view it on GitHub
https://github.com/riot/riot/issues/1387#issuecomment-160887720.

The compiler assumes that the content of tag is HTML if just one line.
It was introduced at v2.0.10 to fix #253. The test code is here:
https://github.com/riot/compiler/blob/dev/test/specs/fixtures/oneline.tag

(Honestly, looks inconsistent a bit for me...)

@cognitom :+1: , we need change the spec to take untagged content as html, for consistence with oneline.
@tipiirai , @GianlucaGuarini , @rsbondi ?

@aMarCruz this is a breaking change maybe we can introduce it in riot 2.4.0. I would like to focus on the other issues for now

@GianlucaGuarini , it is in my TODO for 2.4.0
thanks.

Would this allow you to write the tags into the page with data without having to mount them?

i.e

<things>
{ things: [....] }
</things>

Instead of having to do:

<things></things>

...

riot.mount('things', { things: [...] });

@phillip-haydon no.

With regard to the main discussion, I have found a problem that must be the reason why it was originally decided to take as JS the untagged content: In a page nested script tags can't be used.
This restriction comes from the html spec. So, if the content defaults to html, this can't be done:

<script type="riot/tag">
  <my-tag>
    func(){}
  </my-tag>
</script>

PS: automonting is an interesting idea, but it is not possible at this time.

Ok, yeah the two things I was trying to do was either pass attributes in via the root tag. (like you do in nested tags), or assign JSON inside the tag from within the root (my previous example) for automounting.

Would be awesome to automount in the future if possible.

Thanks for clearing that up.

@aMarCruz - interesting! you mean you can't do

<script type="riot/tag">

  <script>
    ... 
   </script>
</script>

How useful is embedding tags within HTML ?

I think automounting is "magic" and causes unexpected surprises if build inside the core. It's easy to build automounting on your application with a specific CSS class. For example <my-widget class="automount"></my-widget>.

@weepy: You and Einstein are right. The "loose" mode is exactly that magic causing unexpected surprises. I personally prefer the loose mode because of the brevity. But because I don't like options I'm ready to change my habits.

I'm not sure how automounting becomes magic inside core. The fact I have to manually mount the data now makes it feel less like I'm making reusable web components and more like I'm just adding placeholders to the page and throwing HTML Templates everywhere.

Don't get me wrong, Riot is bloody awesome and I absolutely love it. It's more in line with how I feel we should be building web components. You and all the contributors have done an awesome job.

This is literally the only thing I disagree with. :)

Not sure either. Just guessing here without a real use case.

I'm mostly thinking about timing. Should be clear when custom tags are mounted. Sometimes users wants to override a tag before it's mounted.

I hope you are right! I'm always up to ideas that save redundant work/keystrokes.

I would be happy if it was opt in.

riot.autoMount()

Rather than

riot.mount("*")

Altho would it be any different than say:

riot.mount("*")
riot.mount("something-else", {...});

Which I'm effectively doing now.

So if the riot.mount("*") or riot.mount("something-else") was read as options argument is null or undefined, mount any attributes that happen to be on that tag.

That would be the beez kneez. That way I could just mount all and be done with it.

@weepy, right. This is why I changed my mind about this issue.

About embedding, I only use tags on a page for testing, external .tag are less restrictive. The utility depends on the type of application and preferences of each. riot gives this freedom.

Hm. I'd say that not being able to have tag-less contents is a major pitfall for end users, but so is not being able to use <script> in inline tags.

So as far as I can tell, there are two options here:

  1. Expect people using inline tag definitions to use riot.tag instead.
  2. Expect people using tag-less contents to use riot.tag instead.

I'm personally in favour of option 1 - this would create overall more consistent behaviour, and there are quite a few ways to work around this (build tools that can inline externally-defined tags, build tools that can compile inline-defined tags, manually using riot.tag...) that do not result in additional overhead or DOM bloat at runtime.

The workaround mentioned here seems like a stink to me. JavaScript is not a whitespace-sensitive language, and this introduces an additional pitfall.

@joepie91 that comment is not talking about whitescape, it is about one-line tags.

https://github.com/riot/compiler/blob/master/doc/guide.md#one-line-tags

I think we can close this issuenbecause a tags without logic and a template (already an edge case) could be simply used as one-line-tag. I think we should document this on our site

Was this page helpful?
0 / 5 - 0 ratings

Related issues

weepy picture weepy  Â·  54Comments

brianmfranklin picture brianmfranklin  Â·  145Comments

niutech picture niutech  Â·  25Comments

steelbrain picture steelbrain  Â·  21Comments

rsbondi picture rsbondi  Â·  41Comments