Syntax for HTML Island in Script

That kind of syntax does have precedence in E4X, JSX, so it doesn’t seem too unusual to me… I just want to make sure we’re not only considering the use case of immediate output, because I think capturing the result of from an expression is just as important (and wrapping in additional cfsavecontent is nasty).

Slack doesn’t seem to deal with it well, and I think GitHub’s flavour of Markdown might also be an issue because it only uses backticks for code blocks rather than indentation, which means triple backticks inside the code block itself won’t render nicely;
https://help.github.com/articles/creating-and-highlighting-code-blocks/

Nor to me.

Tags are the literal origins of CFML. There is no philosophical leap to allowing tags to co-exist within script, the opposite is already true.

Technically we’re already allowing the parser to switch from tags to script in the middle of a template. This minor change would allow the parser to switch from script to tags in the middle of a template.

Crux…

Many developers believe wholeheartedly, resolutely and passionately in the axiom, “TAGS are bad, SCRIPT is good”. They may even be right.

Others (I’m guessing yourself and myself included) have less freedom and are boxed in by the practical reality of our existing practices, code bases, budgets and resources.

No one is advocating for code abuse in any of its forms.

Axiom implies…

It is perfectly legitimate to have <CFSCRIPT> to allow the creation of a script island in the middle of tags because… TAGS bad, SCRIPT good.

It is not legitimate to have tag { <whatever /> } to allow the creation of a tag island in the middle of script because… TAGS bad, SCRIPT good.

There is nothing useful a tag can do that could not be achieved by writing the code correctly in script; with the exception of a separate view template.

Pragmatism suggests…

The “Axiom” doesn’t help those of us who are stuck with large code bases comprised of tags.

It is useful to be able to insert script into the middle of these “tag” templates, without having to rewrite everything as script.

It would also be useful to leverage existing tag based code by inserting it into “script” templates, without having to rewrite everything as script.

It would also be useful to manipulate tag based constructs like HTML, XML, SVG, etc in small chunks within script based functions without having to resort to external templates, auxiliary files and/or transformation templates.

Personal opinion…

I support the change, if it can do:

  • immediate output
  • captured output
  • all cf tags
  • custom tags

I have no particularly preference for syntax except to say back-ticks… ugh. Anything but back-ticks.

2 Likes

I used to do brown bag lunch presentations every two weeks where my coworkers could come and learn how to write code that was better. It cost me nothing, it cost the company nothing, and for those of my coworkers that showed up regularly they learned invaluable lessons on how to build better applications. After some time doing so, those developers evolved and began adopting the concepts that made sense into their daily work. The result? More maintainable code, more experienced developers, more productivity. Teaching developers to write better code is easy… changing the mindset that ‘My code is just as good as your code’ is the difficult part.

Actually, I’ve never been paid a dime to teach other CFML developers what I know. I’ve gotten a hotel room or two for free presenting at conferences, I’ll admit, but not once have I, personally, ever taken money for mentoring my fellow developers. If anything, this change would actually make teaching others how to build scalable, maintainable, readable, elegant applications more difficult, not easier.

And, as mentioned before, this built in business benefit you perceive would, to the contrary likely be a business detriment, I feel, to having Lucee viewed as ‘Just another crappy CFML engine’ instead of the ‘JVM framework for rapid application development’ it was supposed to be selling itself as.

I said what I had to say… didn’t seem like adding anything else was going to change the outcome either way (until today, when I think I have something constructive to add), so I found other ways to try and help the community and keep myself busy.

I do still agree with @markdrew though… I haven’t actually seen a use case for the CFML tag island that I could see myself selling to a crowd of developers at a conference. It feels like this is something that is just being done because it can be. I’ve still not seen a use case for the CFML tag island that couldn’t be solved in a more elegant and meaningful fashion than the proposed solution. Still on-board with the HTML bits though. That I can sell… the CFML bits? Yeah, not so much.

And also the albatross around the neck of CFML that has thus far prevented widespread adoption of the language by the vast majority of developers. In fact, all metrics say that we’re loosing more CFML developers than we’re gaining. This is, ultimately, unsustainable.

Except:

Which, IMHO, is abuse.

Then you’re not likely to be using cfscript anyway, right? Stick with tags if you want tags, or begin the slow process of rewriting code to cfscript along the way as you have to touch it. Write all new bits in cfscript, convert old bits as and when feasible. Sometimes this means a piecemeal approach must be taken, but the process is pretty cut and dry. You may never get a chance to rewrite everything, granted, but the parts you do end up rewriting will generally be easier to maintain, especially if you adopt any of the design patterns available to you along the way (OO, MVC, FP, etc.).

Which is the one thing I support. This has merit and would be a useful addition to the language. I’d still, personally, use other solutions for rending pipelines, but I can see where this, in particular, would make converting old tag based solutions to cfscript easier.

All this said… I want to bring up a couple of other quick points:

  1. I, too, still have legacy client codebases that are almost entirely tags based. I convert what I can when feasible, write anything new in cfscript when feasible, and go about my day. At no point would I ever consider copy & pasting a block of CFML tags into any cfscript when maintaining or updating these codebases.

  2. I used to be the guy who argued that tags were good. I used to write all of my open source code in tags because, at the time, I thought ‘more people understand tags, so I’m doing them a favor’. Turns out I was wrong on both accounts. I only believe wholeheartedly, resolutely and passionately in the axiom, "TAGS are bad, SCRIPT is good" because I listened to my mentors, like Sean and Adam, who helped me understand the many, many nuanced reasons why I was wrong to keep advocating tags over cfscript. It is unfortunate that neither of them have voiced their opinions here because, frankly, they seemed to do a much better job with me than I seem to be doing with others here. Though, now that I think back on it, I was probably a prick about it with them for a good while before they finally convinced me lol.

1 Like

I’m still on the TAG (technically) and would happily discuss this and any other features there (on the TAG Slack) but, as @markdrew posted there on May 17th: “When was the last time anyone used this? Do we still have a TAG?” – the TAG has been inactive for about a year because there has been no direction from LAS. I’ve complained about that in public several times and @IamSigmund has assured me that it’s on LAS’s radar and will get addressed “soon” (this year).

As for my thoughts on the feature itself, Scala supports XML literals and JavaScript (well, JSX, specifically which is not “JS the language”) supports HTML literals. Those extensions to the base language make sense – Scala lives in the Java ecosystem and has to acknowledge the (awful) sea of XML that surrounds parts of that ecosystem; similarly, JS lives in the browser and has to acknowledge the sea of HTML in which it swims. I think both extensions are seriously ugly but they are specifically limited to XML/HTML so the ugliness is a trade off against a certain specific convenience.

If the proposal offered here was specifically to add inline literals for just XML/HTML as shorthand for string values, then I might be able to get behind it, but my support would be reluctant.

I could never support a proposal for fully evaluated CFML “tag islands” inline. There’s are just so many types of "wrong* in such a concept, from a language design p.o.v. (as well as “optics” from other communities, and “best practices” in terms of separation of concerns, and on and on).

So which of the five proposed syntaxes would get my (very reluctant) vote? 4 – although I will note that both Scala and JSX simply allow an inline XML/HTML literal with no specific delineation and that would be my (very reluctant) preference over 4, but it was not proposed (I suspect it’s harder from an implementation p.o.v. but I don’t really care about that :slight_smile: ).

Note: I’m simply posting this here as my opinion because @ddspringle requested it. I have no desire to justify it because, as we’ve seen, this is a very polarizing issue and I have no energy for this sort of bikeshedding debate (to be honest, this is why language decisions are best left to small groups/committees of dedicated people with either language design experience or exposure to dozens of programming languages over decades of production-level use!).

2 Likes

The problem with syntax option 4

is that the closing brace, } is too ambiguous, and can therefore appear in many different places that are not meant to close the snippet, and therefore require escpaing in those cases.

IMO a syntax should be one that is rare to appear naturally in the context of XML/HTML/*ML

1 Like

Since everyone hates tags, can we just move forward with multi-line strings using ‘’’ and “”"?

Then Igal’s example of:

  savecontent variable="templates.soapCreds" {echo('
    <ns:WebAuthenticationDetail>
       <ns:UserCredential>
          <ns:Key>{key}</ns:Key>
          <ns:Password>{password></ns:Password>
       </ns:UserCredential>
    </ns:WebAuthenticationDetail>
    <ns:ClientDetail>
        <ns:AccountNumber>{accountNumber}</ns:AccountNumber>
        <ns:MeterNumber>{meterNumber}</ns:MeterNumber>
    </ns:ClientDetail>');
}

Becomes:


  templates.soapCreds = '''
    <ns:WebAuthenticationDetail>
       <ns:UserCredential>
          <ns:Key>{key}</ns:Key>
          <ns:Password>{password></ns:Password>
       </ns:UserCredential>
    </ns:WebAuthenticationDetail>
    <ns:ClientDetail>
        <ns:AccountNumber>{accountNumber}</ns:AccountNumber>
        <ns:MeterNumber>{meterNumber}</ns:MeterNumber>
    </ns:ClientDetail>
''';

As stated before, these would be parsed with the expression parser, not the CFML-Tags parser, so no CFML Tags would be interpreted, but #var#'s would.

It would help me to convert Java/Groovy/Other languages to script, something like this for example:


                <cf_groovy node="#ret.getNode()#">
                <cfoutput>
                        import org.htmlcleaner.TagNode;
                        import org.htmlcleaner.TagNodeVisitor;
                        import org.htmlcleaner.HtmlNode;

                        node.traverse(new TagNodeVisitor() {
                                public boolean visit(TagNode tagNode, HtmlNode htmlNode) {
                                        if (htmlNode instanceof TagNode) {
                                                /* Remove all on* attributes, things like javascript actions */
                                                htmlNode.getAttributes()
                                                        .collect() { key, val -> return key?.toLowerCase().startsWith("on")?key:null; }
                                                        .each() { key -> if (key!=null) htmlNode.removeAttribute(key); };
                                                /* remove all IDs */
                                                htmlNode.getAttributes()
                                                        .collect() { key, val -> return key?.equalsIgnoreCase("id")?key:null; }
                                                        .each() { key -> if (key!=null) htmlNode.removeAttribute(key); };
                                                /* remove name attributes from input type elements */
                                                if (htmlNode.getName()?.equalsIgnoreCase("input") || htmlNode.getName()?.equalsIgnoreCase("select") || htmlNode.getName()?.equalsIgnoreCase("textarea")) {
                                                        htmlNode.getAttributes()
                                                                .collect() { key, val -> return key?.toLowerCase()?.equalsIgnoreCase("name")?key:null; }
                                                                .each() { key -> if (key!=null) htmlNode.removeAttribute(key); };
                                                }
                                                /* drop out any input submit buttons */
                                                if (htmlNode.getName()?.equalsIgnoreCase("input") && htmlNode?.getAttributeByName("type")?.equalsIgnoreCase("submit")) {
                                                        htmlNode.removeFromTree();
                                                }
                                        }
                                        return true;
                                }
                        });
                </cfoutput>
                </cf_groovy>

Could then be wrapped in “”" or ‘’’ and allow me to have single ’ and " characters in the code without escaping. It seems like a reasonable compromise.

The CFML community has been bleeding developers for well over a decade.

The main reason for that was that back in the day when there was no Open Source alternative to ColdFusion, the high price seemed exuberant when compared to free alternatives like PHP, JSP, or ASP.

So more and more developers learned those other technologies, and that trend turned into a vicious circle:

1) CFML loses popularity => 
2)   new developers avoid technologies that lose popularity =>
3)     CFML loses popularity even faster =>
4)       back to step (2)

Over the years I looked at those other competing technologies many times, but each time I concluded again that CFML gives me more power and faster development.

If there had been a FOSS CFML engine 15 years ago then we wouldn’t be in this situation.

But now we’re at the point where some people actually “laugh” when they hear “CFML”. Not because they know what they’re talking about, but because of the bad reputation that the language has.

The way to win over new developers though, is not by keeping the status quo. On the contrary! The only way is to innovate, and show other developers how much faster they can develop with CFML compared to their [insert competing platform here].

Take for instance the WebSocket Chat Server example that I published at https://github.com/isapir/lucee-websocket/wiki/Example-Chat#chatlistenercfc – if you remove the comments and extra lines that I added for extra readability – you are left with a multi-channel chat server in about 10 lines of code. I don’t know any platform that allows you to do that, and believe me, I researched the subject a lot before I wrote that extension.

BTW – if you look at the index.cfm example on that page – https://github.com/isapir/lucee-websocket/wiki/Example-Chat#indexcfm – you will see exactly why I proposed this feature here. I would have loved to not have to close the </cfscript> just so that my JavaScript code would be more readable.

This will be even more important in the future, when we will have script-only files that do not require the cfscript tag, because with the absence of an opening <cfscript> tag, I would not be able to close it, leaving me with no option other than adding a separate file and using include.

2 Likes

This also illustrates why a cfoutput tag block is a sensible choice for the syntax to switch into tags :slight_smile:

every script cfc can easy be wrapped in a <cfscript>, so if you wanna break out cfscript, you need to start with a cfscript :wink:

Can this be documented or is it disabled?

It appears to be implemented https://luceeserver.atlassian.net/browse/LDEV-1324 but the example in the description throws “Syntax Error, Invalid Construct”

trycf.com use version 5.2.9.31 of lucee.

1 Like

Yoooooo! I just learned about this feature yesterday. I write 80% of code in Script (components) these days. But, one of the hold-outs for me has always been my Data Access Objects, which I write in Tags so that I can use CFQuery, which still offers easier writing / reading (at least for me) when compared to queryExecute(). So, for me, Tag Islands is almost certainly going to allow me to finally move to Script-based components even for my Data Access Objects.

I put my thoughts on paper:

At this point, the only Tag-based files that I will need are my View files, which is exactly where CFML tags are rock-stars!

8 Likes

In Lucee you can also use the sql attribute in cfquery, so you can also write something like (cfscript example shown):

sqlStatement = "SELECT current_timestamp;"

query name="qTimestamp" sql=sqlStatement;

Avoiding the need for the echo() or writeOutput() call.

1 Like

Ah, very interesting. I’ve dabbled a bit with queryExecute() which feels very similar to that.

They are different methods of doing the same. queryExecute() is a function, while my example uses the cfquery tag - in Lucee every tag can be used in cfscript by removing the namespace cf and and <angle brackets>.
My example would have been clearer in CFML style, though it’s more useful in cfscript (confused? so am I lol):

<cfset sqlStatement = "SELECT current_timestamp;">

<cfquery name="qTimestamp" sql="#sqlStatement#">
1 Like

Ha ha, I love having all the options so that I can choose the right one for the given context :smiley:

1 Like
1 Like

It’s just so awesome!

I’ve been freaking out also!!! See my comments about your blog post here :smiley:

1 Like