Syntax for HTML Island in Script

And this is why we have <cfscript>

I disagree. Building CFCs in tags is the wrong approach for any number of reasons. Readability, for example. Being unable to program in any other language because you refused to use anything but tags is a big reason alone. Lines of code and less typing. I could go on. Tag based CFC’s aren’t just ‘a different way of doing the same thing’, they’re ‘the wrong way to do the same thing’. I’m sorry fi you feel otherwise, but that’s my opinion and I have good reasons for advocating that my fellow CFML developers drop tags like it’s 1999.

I already did. Do you have evidence to support your assertion that outputting tags directly is more performant than the savecontent/writeoutput/echo cycle? What kind of major performance boost do you imagine this would be?

IDE syntax highlighting is something that could be preserved by building a rendering pipeline using templates, or using React, or Angular, or… you get the idea. That said, I would have no problem with a html{} function, if it were limited only to outputting non-evaluated (e.g. HTML/XML) tags. I could see a use for that in rendering templates, but for CFML tags it’s a no bueno from me for the reasons I’ve already stated.

That’s exactly my point. I use mostly cfscript and sometimes there is a need to add a block of markup. So instead of closing the </cfscript>, adding the markup, and then opening a new block of <cfscript>, a “tag island” would allow you to add that markup easily.

I realize that, and that is great. All I said was that the fact that you disagree doesn’t mean that you’re right and anyone who does it differently is doing it wrong.

Major performance boost. Performance is one of the top goals of Lucee, so we test stuff like this all the time, but even without testing it I can tell you that it is much slower to add savecontent which will create a new buffer, set it to a variable, and then another method call to read back that variable and write it to the response stream.

Each tag or function call adds a lot of overhead. Take for example the following snippet:

<cfscript>
	iter = 1000000;

	function add(a){ return arguments.a + 1; }

	timer label="function" {
		for (i=0; i<iter; i++)
			b = add(i, 1);
	}

	timer label="inline" {
		for (i=0; i<iter; i++)
			b = i + 1;
	}
</cfscript>

On my machine inline runs about 3 to 5 times faster than function, and that’s for a single function call without doing anything else.

Why add a whole framework for something so simple? And then deal with two languages (JavaScript) instead of one?

This is exactly the point! If you had started with that then it would have saved me much typing :wink:

The idea is not to start writing CFML tags in that “tag island”, it’s mostly to write HTML markup. But it can make life easier also when using some tags like <cfmail>, and <cfquery>.

Or if you want to render HTML markup with some values that are interpreted by Lucee, e.g. <td>#name#</td>, so it doesn’t make sense to add it and then have to write <td><cfset echo(name)></td>

Of course, all thoughts are welcome!

My points in regards to JSX are fairly straight forward;

  1. The “end result” of JSX is an object, as I already acknowledged
  2. It shows that this style of syntax has a widely accepted precedent
  3. You can either place JSX inline with script, or place it into a separate file; it’s up to the developer, sometimes inline is actually best

The query example was just that; a way to point out that a quite readable and usable syntax could exist, and might work with existing built-ins. You wouldn’t have to use it, but IMO there’s also nothing wrong with others preferring it :wink: If you have any kind of large, dynamic query, queryExecute might be more verbose in comparison, and slightly less readable, but for most simple queries it’s fantastic, no doubt!

The custom tags example, I think, is totally reasonable. You might not want to hand craft complex SVG, but you may have some other machinery that helps you build it in a simple way. Why would you repeat complex templating that is likely to change when you can abstract it? This concept can be extended to any type of output or returnable objects, we don’t have to fixate on the concrete example of SVG (or on HTML in the case of the other examples). Custom tags are perfectly fine for any of these scenarios, and they provide a construct that simply doesn’t work well in the current script equivalents (the ACF implementation is bad).

React developers might disagree. I think the point is everyone wants to use script everywhere, except in a few specific cases when tags could do the job better :smiley:

Aye, I’m still keen for script based files that are not components!

1 Like

This isn’t about me being right or wrong. I’m not scratching my ego here. It’s about there being a right way and a wrong way to build maintainable applications.

It’s the difference between using super glue or bubble gum to hold a broken vase together. Bubble gum will get the job done in the short term, but it isn’t the right way to put the vase back together if you expect it to stand the test of time.

Another apples and oranges comparison. Last time I checked I’m not iterating over 1M records and outputting HTML. I’m not arguing that you might shave a ms or two by not using savecontent, but in the general use case 1 or 2 ms isn’t worth investing time into this functionality IMHO. And, again, there are better, well defined, solutions to the problem - you just don’t want to use them, which is fine, but investing LAS time into this functionality really just isn’t high on my list of wants. I’ll probably never use it, personally.

Because ColdFusion isn’t a hammer and applications aren’t nails.Those frameworks deal exactly with the problems posed by having to dynamically render HTML from data and are well suited for that purpose. Why would I want to reinvent a wheel in ColdFusion that’s already handled, quite nicely, by other frameworks?

Sorry, I cringe every time you mention <cfquery> or <cfmail> being used inside a tag island. While the idea, for you, may not to be to start writing CFML tags inside the island… I guarantee you that if you do this, that is exactly what many CFML developers will do. This would seem to me to exacerbate one problem to simply swat at another one.

Again, if you want an html{} function that evaluates dynamic content inside of markup while maintaining IDE coloring, I’m all for it. If you want to be able to write any CFML tags in cfscript, then I’m completely against that.

2 Likes

Yes, as a rendering pipeline. Again, this is different from what is being requested here. Completely.

This:

function Repeat(props) {
  let items = [];
  for (let i = 0; i < props.numTimes; i++) {
    items.push(props.children(i));
  }
  return <div>{items}</div>;
}

function ListOfTenThings() {
  return (
    <Repeat numTimes={10}>
      {(index) => <div key={index}>This is item {index} in the list</div>}
    </Repeat>
  );
}

is not this:

tags{
<div>
    <cfloop from="1" to="10" index="ix">
        <div>This is item #ix# in the list</div>
    </cfloop>
</div>
}

The tags are placeholders for the rendering pipeline that evaluates the JSX tag and renders the appropriate HTML in it’s place.

And my argument is that if you open this door most developers will abuse the functionality in every conceivable way possible. The intent may be that it is used sparingly, in lieu of using a rendering pipeline and templates, or in lieu of a (possibly) more verbose and less readable query, for example, but in reality it is far more likely to be widely abused and result in even more horrid spaghetti code to be held up as examples of the shoddy quality of work CFML allows.

1 Like

The intent would be to re-enable some practical, useful, and powerful constructs in script based files. It’s ok if you don’t see it as a win, but I don’t think the hyperbole is helping your argument?

Tag based components are still a thing. You can write one right now. Do you think a developer is of less worth if they choose to make use of some custom tags which are used as a DSL in a tag based component? Why not enable this functionality in a script based component?

Not everything is black and white! :slight_smile:

1 Like

If we are enabling scripting of tag islands just because of failures in cfmail and cfquery implementations that is a bad thing.

The base components of those tags are badly created. I have had to re-implement the Mail component as:

  var email = new EMail()
                            .to(to.getPrimaryEmailFormatted())
                            .from(emailConfig.fromEmail)
                            .subject(emailinfo.subject)
                            .body( emailinfo.text )
                            .html( emailinfo.html )
                            .send();

which is miles better than the current implementation.

My point being is provide good use cases for code islands please :slight_smile:

3 Likes

Talk about “apples and oranges”, good thing you didn’t use “welding vs. spit”. This is an irrelevant analogy as there is no indication that the other way is “bubble gum” as you put it.

Performance measuring is a relative. If something takes 10 to 20 times longer then it’s much much slower. Every performance or benchmark test is done in a loop so I’m really surprised that now you are questioning the method of measuring and comparing.

If you have 1000 concurrent requests then 2ms become 2s and your application is somewhere between slow and unresponsive. If you don’t build applications for scalability then perhaps that doesn’t make a difference to you.

When I add a feature or fix a bug myself then I do it on my own time, so this is not LAS time, and it is not paid for by your support dollars if you are a supporter of the project.

TBH, more time has probably been spent on this thread than implementing the feature.

It is not hyperbole to suggest that CFML has had an albatross around it’s neck for over a decade because of it’s tag based nature and ease of abuse. That’s just a fact. Giving CFMl developers the opportunity to write CFML tags inside of script is going to exacerbate that ease of abuse. That is also a fact. The history of most CFML developers (those outside of our little circle here, mostly) is that they abuse the language, primarily because they don’t really understand programming. That is also a fact. I worked in DC with 5 taggers most of my career and I can absolutely guarantee that if you allow them to write tags in script, they will abuse it. That’s not hyperbole, it’s experience.

Sadly, they are still a thing for some. And I could write one right now, but I won’t.

I am not here to evaluate the worth of any developer. I’m suggesting that tag based CFCs are the wrong approach. Allowing CFML tags in script because the custom tag implementation isn’t well suited to script based CFCs is also the wrong approach. The right approach is to fix the custom tag implementation.

I’m not suggesting it is, I’m suggesting that it’s the wrong approach to the problems you’re trying to solve.

Which is great if you already have the “html” markup ready and passed as an argument. In that case you don not need a Component – simply pass the attribute, or a body param.

The need arises if you want a small snippet of html while writing your script code, without loading it from an external source (db, file).

So instead of putting it all in a string and escaping quotes and having no chance at syntax coloring, you add some markup in a tag island.

So this is just replacing variables in HTML right?

I would really limit what you can do with it, so you can do HTML and replace vars. So you do a moustache parser such as:

html (

<h1>{{title}}</h1>
{{body}}

You ordered:
<ul>
{{each array}}
    <li>{{thing.name}}</li>
{{/each}}
</ul>
)

Then add it as an extension, but a lot of features should have more discussion before implementation as you can’t take bad features back!

3 Likes

Not everything can be added as an extension. This is part of the parsing and compilation process.

Then we definitely SHOULD have more discussion about a core feature before implementing it!!!

Come up with a good marketing (to developers) use case (as you did above) and we can come up with a logical solution.

Randomly adding cftags within script just because you can do it is terrible and not good language design. It will be added to lucee and live with us forever (this is from someone that has to go to old codebases and help people out all the time)

That’s exactly the perception of every Polyglot I’ve ever known, and I happen to agree with them. True, or not, perception matters. I would like to see adoption of CFML increase. That is unlikely to happen so long as we hold up examples of bubble gum holding scraps of tags together.

I made no such assertion and was not questioning your methodology.

You’re advocating to include CFML tags inside of script, and then you want to school me on performance? Seriously?

And I appreciate the time you have or will or would spend on this ‘feature’ and your contributions to the project. I, however, would refuse to merge any feature that allows CFML tags inside of script. But thankfully I don’t have that kind of authority so you are free to roam about the cabin as you wish :wink:

As well it should. Discussion of this kind of feature is important to many people, and just because you feel you have a useful solution does not mean it should be implemented into the language willy nilly.

It is important to have these discussions, to flesh out what is and is not appropriate for the language, and to find alternative solutions to the problems you are having implementing everything you want purely with cfscript. Fixing the problems, not applying a band-aid, especially one that can be abused so freely, is the right approach IMHO.

Replace(imageText, 'scientists', 'developers','all')

So Mustache Parser is OK but this feature is NOT?

And where exactly do you put that “html” node at the top? Is that a function? A tag?

OK, you win. I can not compete with overly used movie quotes and memes.

1 Like

I was providing an example, whether it was as text within a function or not. I already wrote moustache and markdown parsers for railo so it’s not a biggy, but that is beside the point.

If it was a function you can swamp out how you parse text (such as using markdown vs moustache) . Maybe give it access to the variables scope so that it works how you expect it. but the point being not to give it acccess to the whole kit and kaboodle.

var html = moustache ('
<h1>{{title}}</h1>
Dear {{variables.fullName}}

You ordered:
<ul>
{{each local.OrderArray}}
    <li>{{ProductName}} - {{ProductPrice}}</li>
{{/each}}
</ul>

')

So you resort to string again, which is exactly the thing to avoid for the reasons I itemized above!

Please read above. It doesn’t make sense to keep on writing the same thing over and over again.