jade template engine - defining new operators - template-engine

Is is possible to define new operators using jade?
Similar to the abbreviations in emmet.
I would like to define something like
k=v
to be
<op key="k" value="v"/>
and
k eq 1
to be
<find value="k = 1"/>
(While I like zencoding / emmet I sometimes find it to be too terse.)
If not Jade maybe something similar?

No, Emmet doesn’t support custom operators. And, in case of your examples, it requires completely different parser which you’ll likely have to write by yourself.
However, you can utilize Emmet syntax to create something similar. For example, with this snippet definition:
"op": "<op key=\"${id}\" value=\"${class}\" />"
you can expand op#k.v abbreviation to get desired result.

Related

Wrap all the strings with single quotas

Let's assume that my template is like a following
string1=${obj.firstString}
string2=${obj.secondString}
number1=${obj.firstNumber}
I'm looking for some automatic way to wrap all my string parameters with single quotas? The expected output is
string1='A'
string2='B'
number1=42
I understand that I can write string1=${"'" + obj.firstString + "'"} , but maybe there is some more conventional way for this requirement...
Thanks a lot!
I would just do this:
string1='${obj.firstString}'
string2='${obj.secondString}'
number1=${obj.firstNumber}
It's a template language, so the basic idea is to make your program look similar to its own output.

Forcing string interpolation in Jade

I am trying to use Jade to do some string interpolation + i18n
I wrote a custom tag
mixin unsubscribe
a(title='unsubscribe_link', href='#{target_address}/',
target='_blank', style='color:#00b2e2;text-decoration:none;')
= __("Click here")
Then I got the following to work
p
| #[+unsubscribe] to unsubscribe
However, in order to support i18n I would also like to wrap the the whole string in a translation block the function is called with __().
But when I wrap the string in a code block it no longer renders the custom tag.
p
| #{__("#[+unsubscribe] to unsubscribe")}
p
= __("#[+unsubscribe] to unsubscribe")
will output literally [+unsubscribe] to unsubscribe. Is there a way to force the returned string from the function?
Edit 1
As has been pointed out, nesting the "Click here" doesn't really make sense, since it will be creating separate strings.
My goal with all this is really to create a simplified text string that can be passed off to a translation service:
So ideally it should be:
"#[+unsubscribe('Click here')] to unsubscribe"
and I would get back
"Klicken Sie #[+unsubscribe hier] um Ihr auszutragen"
My reasoning for this is that because using something like gettext will match by exact strings, I would like to abstract out all the logic behind the tag.
What you really want to achieve is this:
<p>
<a href='the link' title='it should also be translated!'
target='_blank' class='classes are better'>Click here</a> to unsubscribe
</p>
And for some reason you don't want to include tags in the translation. Well, unfortunately separating 'Click here' from 'to unsubscribe' will result in incorrect translations for some languages - the translator needs a context. So it is better to use the tag.
And by the way: things like __('Click here') doesn't allow for different translation of the string based on context. I have no idea what translation tool you're using, but it should definitely use identifiers rather than English texts.
Going back to your original question, I believe you can use parametrized mixin to do it:
mixin unsubscribe(title, target_address, click_here, to_unsubscribe)
a(title=title, href=target_address, target='_blank', style='color:#00b2e2;text-decoration:none;')= click_here
span= to_unsubscribe
This of course will result in additional <span> tag and it still does not solve the real issue (separating "Click here" from "to unsubscribe") and no way to re-order this sentence, but... I guess the only valid option would be to have interpolation built-in into translation engine and writing out unescaped tag. Otherwise you'd need to redesign the page to avoid link inside the sentence.

Find HTML Tags in Properties

My current issue is to find HTML-Tags inside of property values. I thought it would be easy to search with a query like /jcr:root/content/xgermany//*[jcr:contains(., '<strong>')] order by #jcr:score
It looks like there is a problem with the chars < and > because this query finds everything which has strong in it's property. It finds <strong>Some Text</strong> but also This is a strong man.
Also the Query Builder API didn't helped me.
Is there a possibility to solve it with a XPath or SQL Query or do I have to iterate through the whole content?
I don't fully understand why it finds This is a strong man as a result for '<strong>', but it sounds like the unexpected behavior comes from the "simple search-engine syntax" for the second argument to jcr:contains(). Apparently the < > are just being ignored as "meaningless" punctuation.
You could try quoting the search term:
/jcr:root/content/xgermany//*[jcr:contains(., '"<strong>"')]
though you may have to tweak that if your whole XPath expression is enclosed in double quotes.
Of course this will not be very robust even if it works, since you're trying to find HTML elements by searching for fixed strings, instead of actually parsing the HTML.
If you have an specific jcr:primaryType and the targeted properties you can do something like this
select * from nt:unstructured where text like '%<strong>%'
I tested it , but you need to know the properties you are intererested in.
This is jcr-sql syntax
Start using predicates like a champ this way all of this will make sense to you!
HTML Encode <strong>
HTML Decimal <strong>
Query builder is your friend:
Predicates: (like a CHAMP!)
path=/content/geometrixx
type=nt:unstructured
property=text
property.operation=like
property.value=%<strong>%
Have go here:
http://localhost:4502/libs/cq/search/content/querydebug.html?charset=UTF-8&query=path%3D%2Fcontent%2Fgeometrixx%0D%0Atype%3Dnt%3Aunstructured%0D%0Aproperty%3Dtext%0D%0Aproperty.operation%3Dlike%0D%0Aproperty.value%3D%25%3Cstrong%3E%25
Predicates: (like a CHAMP!)
path=/content/geometrixx
type=nt:unstructured
property=text
property.operation=like
property.value=%<strong>%
Have a go here:
http://localhost:4502/libs/cq/search/content/querydebug.html?charset=UTF-8&query=path%3D%2Fcontent%2Fgeometrixx%0D%0Atype%3Dnt%3Aunstructured%0D%0Aproperty%3Dtext%0D%0Aproperty.operation%3Dlike%0D%0Aproperty.value%3D%25%26lt%3Bstrong%26gt%3B%25
XPath:
/jcr:root/content/geometrixx//element(*, nt:unstructured)
[
jcr:like(#text, '%<strong>%')
]
SQL2 (already covered... NASTY YUK..)
SELECT * FROM [nt:unstructured] AS s WHERE ISDESCENDANTNODE([/content/geometrixx]) and text like '%<strong>%'
Although I'm sure it's entirely possible with a string of predicates, it's possibly heading down the wrong route. Ideally it would be better to parse the HTML when it is stored or published.
The required information would be stored on simple properties on the node in question. The query will then be a lot simpler with just a property = value query, than lots of overly complex query syntax.
It will probably be faster too.
So if you read in your HTML with something like HTMLClient and then parse it with a OSGI service, that can accurately save these properties for you. Every time the HTML is changed the process would update these properties as necessary. Just some thoughts if your SQL is getting too much.

Ruby, regex, sentences

I'm currently building a code generator, which aims to generate boiler plate for me once I write the templates and/or translations, in whatever language I have to work with.
I have a problem with a regex in Ruby. The regex aims to select whatever is between {{{ and }}}, so I can generate functions according to my needs.
My regex is currently :
/\{\{\{(([a-zA-Z]|\s)+)\}\}\}/m
My test data set is:
{{{Demande aaa}}} => {{{tagadatsouintsouin tutu}}}
The results are:
[["Demande aaa", "a"], ["tagadatsouintsouin tutu", "u"]]
Each time the regex picks the last character twice. That's not exactly what I want, I need something more like this:
/\{\{\{((\w|\W)+)\}\}\}/m
But this has a flaw too, the results are:
[["Demande aaa}}} => {{{tagadatsouintsouin tutu", "u"]]
Whereas, I wish to get:
[["Demande aaa"],["tagadatsouintsouin tutu"]]
How do I correct these regexes? I could use two sets of delimiters, but it won't teach me anything.
Edit :
All your regex run against my data sample, so you all got a point.
Regex may be overkill, and probably are overkill for my purpose. So i have two questions.
First, do the regex keep the same exact indentation ? This should be able to handle whole functions.
Second, is there something fitter for that task ?
Detailled explanation of the purpose of this tool. I'm bored to write boiler plate code in php - symfony. So i wish to generate this according to templates.
My intent is to build some views, some controllers, and even parts of model this way.
Pratical example : In my model, i wish to generate some functions according to the type of an object's attribute. For examples, i have functions displaying correctly money. So i need to build the corect function, according to my attribute, and then put in , inside m output file.
So there is some translations which themselves need translations.
So a fictive example :
{{{euro}}} => {{{ function getMyAttributeEuro()
{
return formating($this->get[[MyAttribute]]);
} }}}
In order to stock my translations, should i use regex, like
I wish to build something a bit clever, so it can build most of the basic code with no bug. So i can work on interesting code.
You have one set of capturing parentheses too many.
/\{\{\{([a-zA-Z\s]+)\}\}\}/
Also, you don't need the /m modifier because there is no dot (.) in your regex whose behaviour would be affected by it.
I'm partial to:
data = '{{{Demande aaa}}} => {{{tagadatsouintsouin tutu}}}'
data.scan(/\{{3}(.+?)}{3}/).flatten.map{ |r| r.squeeze(' ') }
=> ["Demande aaa", "tagadatsouintsouin tutu"]
or:
data.scan(/\{{3}(.+?)}{3}/).flatten.map{ |r| [ r.squeeze(' ') ] }
=> [["Demande aaa"], ["tagadatsouintsouin tutu"]]
or:
data.scan(/\{{3}(.+?)}{3}/).map{ |r| [ r[0].squeeze(' ') ] }
=> [["Demande aaa"], ["tagadatsouintsouin tutu"]]
if you need the sub-arrays.
I'm not big on trying to everything possible inside the regex. I prefer to keep it short and sweet, then polish the output once I've found what I was looking for. It's a maintenance issue, because regex make my head hurt, and I stopped thinking of them as a macho thing years ago. Regex are a very useful tool, but too often they are seen as the answer to every problem, which they're not.
Some people, when confronted with a problem, think “I know,
I'll use regular expressions.” Now they have two problems.
-- Jamie Zawinski
You want non capturing groups (?:...), but here is another way.
/\{\{\{(.*?)\}\}\}/m
Just a shot
/\{\{\{([\w\W]+?)\}\}\}/
Added non-greedyness to your regex
Here this seems to work

how to replace a string in a ruby file after a match is found

I have a xml file, which i need to modify from my ruby script and save it. xml file looks something like
`
<mtn:messages>
<mtn:message correlation-key="0x" sequence="4">
<mtn:header>
<mtn:protocol-version>0x4</mtn:protocol-version>
<mtn:message-type>0x0F04</mtn:message-type>
<mtn:ttl>4</mtn:ttl>
<mtn:qos-class-of-service>0</mtn:qos-class-of-service>
<mtn:qos-priority>2</mtn:qos-priority>
</mtn:header>
</mtn:message>
</mtn:messages>
</mtn:test-case>
<mtn:test-case title="Train-Consist-Message">
<mtn:messages>
<mtn:message correlation-key="0x" sequence="4">
<mtn:header>
<mtn:protocol-version>0x4</mtn:protocol-version>
<mtn:message-type>0x0F04</mtn:message-type>
<mtn:ttl>4</mtn:ttl>
<mtn:qos-class-of-service>0</mtn:qos-class-of-service>
<mtn:qos-priority>2</mtn:qos-priority>
</mtn:header>
</mtn:message>
</mtn:messages>
</mtn:test-case>`
I need to replace <mtn:ttl>4</mtn:ttl> with <mtn:ttl>some other value</mtn:ttl> which comes under <mtn:test-case title="Train-Consist-Message"> and save it.
I have written below code, but its replacing all occurances of <mtn:ttl>4</mtn:ttl>.
`doc = IO.read(ENV['CadPath1']+ "conf\\cad-mtn-config.xml")
doc.gsub!(pattern, str)
File.open("File path", "w"){|fh| fh.write(doc)}`
Please help me with this. Waiting for your early reply...
String#gsub! modifies the string in-place, replacing all instances with the replacement specified. If you only want to replace the first instance, use String#sub or String.sub!.
The suggestion from Mike about using sub instead of gsub is good. But parsing XML (and HTML) with regular expression is usually frowned upon.
From your question I assume that you locate the to-be-modified element in terms of parent-child relations, not in terms of the source code order (i.e. you will not be able to say: "modify the second occurrence of this pattern"), so inventing a reliable regular expressions may be very, very hard.
You should use a parser library to find the element you want to change. There is a pretty large collection of those. See some of them at http://ruby-toolbox.com/categories/html_parsing.html and pick one, or use a built-in REXML library.
Alternatively, you could use a very simple 'html-scanner' module, which is included in Rails' ActionController (action_controller/vendor/html-scanner.rb), but if you do not use Rails, I am not sure whether extracting it is worth your time.
The exact code will depend on the parser you choose. Usually they have pretty good documentation/tutorials, so I am sure you will be able to handle it.

Resources