I forked the excellent zen-coding project, with an idea to implement DOM ascension using a ^ - so you can do:
html>head>title^body>h1
rather than html>(head>title)+body>h1
Initially I implemented with rather shoddy regex methods. I have now implemented using @Jordan's excellent answer. My fork is here
Are there any scenarios where my function returns the wrong value?
Disclaimer: I have never used zen-coding and this is only my second time hearing about it, so I have no idea what the likely gotchas are. That said, this seems to be a working solution, or at least very close to one.
I am using Zen Coding for textarea v0.7.1 for this. If you are using a different version of the codebase you will need to adapt these instructions accordingly.
A couple of commenters have suggested that this is not a job for regular expressions, and I agree. Fortunately, zen-coding has its own parser implementation, and it's really easy to build on! There are two places where you need to add code to make this work:
Add the ^ character to the special_chars
variable in the isAllowedChar
function (starts circa line 1694):
function isAllowedChar(ch) {
...
special_chars = '#.>+*:$-_!@[]()|^'; // Added ascension operator "^"
Handle the new operator in the switch
statement of the parse
function (starts circa line 1541):
parse: function(abbr) {
...
while (i < il) {
ch = abbr.charAt(i);
prev_ch = i ? abbr.charAt(i - 1) : '';
switch (ch) {
...
// YOUR CODE BELOW
case '^': // Ascension operator
if (!text_lvl && !attr_lvl) {
dumpToken();
context = context.parent.parent.addChild();
} else {
token += ch;
}
break;
Here's a line-by-line breakdown of what the new code does:
case '^': // Current character is ascension operator.
if (!text_lvl && !attr_lvl) { // Don't apply in text/attributes.
dumpToken(); // Operator signifies end of current token.
// Shift context up two levels.
context = context.parent.parent.addChild();
} else {
token += ch; // Add char to token in text/attribute.
}
break;
The implementation above works as expected for e.g.:
html>head>title^body
html:5>div#first>div.inner^div#second>div.inner
html:5>div>(div>div>div^div)^div*2
html:5>div>div>div^^div
You will doubtless want to try some more advanced, real-world test cases. Here's my modified source if you want a kick-start; replace your zen_textarea.min.js
with this for some quick-and-dirty testing.
Note that this merely ascends the DOM by two levels and does not treat the preceding elements as a group, so e.g. div>div^*3
will not work like (div>div)*3
. If this is something you want then look at the logic for the closing parenthesis character, which uses a lookahead to check for multiplication. (Personally, I suggest not doing this, since even for an abbreviated syntax it is horribly unreadable.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With