Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
C
CodeMirror
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Issue analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Moritz Aurel Pascal Schubotz
CodeMirror
Commits
65c74d59
Commit
65c74d59
authored
11 years ago
by
Ben Keen
Committed by
Marijn Haverbeke
11 years ago
Browse files
Options
Downloads
Patches
Plain Diff
[smarty mode] Rewrite, Smarty 3 support added
Issue #956
parent
d07c5471
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
mode/smarty/index.html
+44
-1
44 additions, 1 deletion
mode/smarty/index.html
mode/smarty/smarty.js
+157
-111
157 additions, 111 deletions
mode/smarty/smarty.js
with
201 additions
and
112 deletions
mode/smarty/index.html
+
44
−
1
View file @
65c74d59
...
...
@@ -12,6 +12,7 @@
<body>
<h1>
CodeMirror: Smarty mode
</h1>
<h3>
Default settings (Smarty 2,
<b>
{
</b>
and
<b>
}
</b>
delimiters)
</h3>
<form><textarea
id=
"code"
name=
"code"
>
{extends file="parent.tpl"}
{include file="template.tpl"}
...
...
@@ -43,6 +44,7 @@
<br
/>
<h3>
Smarty 2, custom delimiters
</h3>
<form><textarea
id=
"code2"
name=
"code2"
>
{--extends file="parent.tpl"--}
{--include file="template.tpl"--}
...
...
@@ -76,7 +78,48 @@
});
</script>
<p>
A plain text/Smarty mode which allows for custom delimiter tags (defaults to
<b>
{
</b>
and
<b>
}
</b>
).
</p>
<br
/>
<h3>
Smarty 3
</h3>
<textarea
id=
"code3"
name=
"code3"
>
Nested tags {$foo={counter one=1 two={inception}}+3} are now valid in Smarty 3.
<script>
function
test
()
{
console
.
log
(
"
Smarty 3 permits single curly braces followed by whitespace to NOT slip into Smarty mode.
"
);
}
</script>
{assign var=foo value=[1,2,3]}
{assign var=foo value=['y'=>'yellow','b'=>'blue']}
{assign var=foo value=[1,[9,8],3]}
{$foo=$bar+2} {* a comment *}
{$foo.bar=1} {* another comment *}
{$foo = myfunct(($x+$y)*3)}
{$foo = strlen($bar)}
{$foo.bar.baz=1}, {$foo[]=1}
Smarty "dot" syntax (note: embedded {} are used to address ambiguities):
{$foo.a.b.c} => $foo['a']['b']['c']
{$foo.a.$b.c} => $foo['a'][$b]['c']
{$foo.a.{$b+4}.c} => $foo['a'][$b+4]['c']
{$foo.a.{$b.c}} => $foo['a'][$b['c']]
{$object->method1($x)->method2($y)}
</textarea>
<script>
var
editor
=
CodeMirror
.
fromTextArea
(
document
.
getElementById
(
"
code3
"
),
{
lineNumbers
:
true
,
mode
:
"
smarty
"
,
smartyVersion
:
3
});
</script>
<p>
A plain text/Smarty version 2 or 3 mode, which allows for custom delimiter tags.
</p>
<p><strong>
MIME types defined:
</strong>
<code>
text/x-smarty
</code></p>
</body>
...
...
This diff is collapsed.
Click to expand it.
mode/smarty/smarty.js
+
157
−
111
View file @
65c74d59
/**
* Smarty 2 and 3 mode.
*/
CodeMirror
.
defineMode
(
"
smarty
"
,
function
(
config
)
{
var
keyFuncs
=
[
"
debug
"
,
"
extends
"
,
"
function
"
,
"
include
"
,
"
literal
"
];
"
use strict
"
;
// our default settings; check to see if they're overridden
var
settings
=
{
rightDelimiter
:
'
}
'
,
leftDelimiter
:
'
{
'
,
smartyVersion
:
2
// for backward compatibility
};
if
(
config
.
hasOwnProperty
(
"
leftDelimiter
"
))
{
settings
.
leftDelimiter
=
config
.
leftDelimiter
;
}
if
(
config
.
hasOwnProperty
(
"
rightDelimiter
"
))
{
settings
.
rightDelimiter
=
config
.
rightDelimiter
;
}
if
(
config
.
hasOwnProperty
(
"
smartyVersion
"
)
&&
config
.
smartyVersion
===
3
)
{
settings
.
smartyVersion
=
3
;
}
var
keyFunctions
=
[
"
debug
"
,
"
extends
"
,
"
function
"
,
"
include
"
,
"
literal
"
];
var
last
;
var
regs
=
{
operatorChars
:
/
[
+
\-
*&%=<>!?
]
/
,
validIdentifier
:
/
[
a-zA-Z0-9
\
_]
/
,
stringChar
:
/
[
\'\
"]
/
validIdentifier
:
/
[
a-zA-Z0-9_
]
/
,
stringChar
:
/
[
'
"
]
/
};
var
leftDelim
=
(
typeof
config
.
mode
.
leftDelimiter
!=
'
undefined
'
)
?
config
.
mode
.
leftDelimiter
:
"
{
"
;
var
rightDelim
=
(
typeof
config
.
mode
.
rightDelimiter
!=
'
undefined
'
)
?
config
.
mode
.
rightDelimiter
:
"
}
"
;
function
ret
(
style
,
lst
)
{
last
=
lst
;
return
style
;
}
function
tokenizer
(
stream
,
state
)
{
function
chain
(
parser
)
{
var
helpers
=
{
continue
:
function
(
style
,
lastType
)
{
last
=
lastType
;
return
style
;
},
chain
:
function
(
stream
,
state
,
parser
)
{
state
.
tokenize
=
parser
;
return
parser
(
stream
,
state
);
}
};
if
(
stream
.
match
(
leftDelim
,
true
))
{
if
(
stream
.
eat
(
"
*
"
))
{
return
chain
(
inBlock
(
"
comment
"
,
"
*
"
+
rightDelim
));
}
else
{
state
.
tokenize
=
inSmarty
;
return
"
tag
"
;
}
}
else
{
// I'd like to do an eatWhile() here, but I can't get it to eat only up to the rightDelim string/char
stream
.
next
();
return
null
;
}
}
function
inSmarty
(
stream
,
state
)
{
if
(
stream
.
match
(
rightDelim
,
true
))
{
state
.
tokenize
=
tokenizer
;
return
ret
(
"
tag
"
,
null
);
}
// our various parsers
var
parsers
=
{
var
ch
=
stream
.
next
();
if
(
ch
==
"
$
"
)
{
stream
.
eatWhile
(
regs
.
validIdentifier
);
return
ret
(
"
variable-2
"
,
"
variable
"
);
}
else
if
(
ch
==
"
.
"
)
{
return
ret
(
"
operator
"
,
"
property
"
);
}
else
if
(
regs
.
stringChar
.
test
(
ch
))
{
state
.
tokenize
=
inAttribute
(
ch
);
return
ret
(
"
string
"
,
"
string
"
);
}
else
if
(
regs
.
operatorChars
.
test
(
ch
))
{
stream
.
eatWhile
(
regs
.
operatorChars
);
return
ret
(
"
operator
"
,
"
operator
"
);
}
else
if
(
ch
==
"
[
"
||
ch
==
"
]
"
)
{
return
ret
(
"
bracket
"
,
"
bracket
"
);
}
else
if
(
/
\d
/
.
test
(
ch
))
{
stream
.
eatWhile
(
/
\d
/
);
return
ret
(
"
number
"
,
"
number
"
);
}
else
{
if
(
state
.
last
==
"
variable
"
)
{
if
(
ch
==
"
@
"
)
{
stream
.
eatWhile
(
regs
.
validIdentifier
);
return
ret
(
"
property
"
,
"
property
"
);
// the main tokenizer
tokenizer
:
function
(
stream
,
state
)
{
if
(
stream
.
match
(
settings
.
leftDelimiter
,
true
))
{
if
(
stream
.
eat
(
"
*
"
))
{
return
helpers
.
chain
(
stream
,
state
,
parsers
.
inBlock
(
"
comment
"
,
"
*
"
+
settings
.
rightDelimiter
));
}
else
{
// Smarty 3 allows { and } surrounded by whitespace to NOT slip into Smarty mode
state
.
depth
++
;
var
isEol
=
stream
.
eol
();
var
isFollowedByWhitespace
=
/
\s
/
.
test
(
stream
.
peek
());
if
(
settings
.
smartyVersion
===
3
&&
settings
.
leftDelimiter
===
"
{
"
&&
(
isEol
||
isFollowedByWhitespace
))
{
state
.
depth
--
;
return
null
;
}
else
{
state
.
tokenize
=
parsers
.
smarty
;
last
=
"
startTag
"
;
return
"
tag
"
;
}
}
else
if
(
ch
==
"
|
"
)
{
stream
.
eatWhile
(
regs
.
validIdentifier
);
return
ret
(
"
qualifier
"
,
"
modifier
"
);
}
}
else
if
(
state
.
last
==
"
whitespace
"
)
{
stream
.
eatWhile
(
regs
.
validIdentifier
);
return
ret
(
"
attribute
"
,
"
modifier
"
);
}
else
if
(
state
.
last
==
"
property
"
)
{
stream
.
eatWhile
(
regs
.
validIdentifier
);
return
ret
(
"
property
"
,
null
);
}
else
if
(
/
\s
/
.
test
(
ch
))
{
last
=
"
whitespace
"
;
}
else
{
stream
.
next
();
return
null
;
}
},
var
str
=
""
;
if
(
ch
!=
"
/
"
)
{
str
+=
ch
;
}
var
c
=
""
;
while
((
c
=
stream
.
eat
(
regs
.
validIdentifier
)))
{
str
+=
c
;
}
var
i
,
j
;
for
(
i
=
0
,
j
=
keyFuncs
.
length
;
i
<
j
;
i
++
)
{
if
(
keyFuncs
[
i
]
==
str
)
{
return
ret
(
"
keyword
"
,
"
keyword
"
);
// parsing Smarty content
smarty
:
function
(
stream
,
state
)
{
if
(
stream
.
match
(
settings
.
rightDelimiter
,
true
))
{
if
(
settings
.
smartyVersion
===
3
)
{
state
.
depth
--
;
if
(
state
.
depth
<=
0
)
{
state
.
tokenize
=
parsers
.
tokenizer
;
}
}
else
{
state
.
tokenize
=
parsers
.
tokenizer
;
}
return
helpers
.
continue
(
"
tag
"
,
null
);
}
if
(
/
\s
/
.
test
(
ch
))
{
return
null
;
if
(
stream
.
match
(
settings
.
leftDelimiter
,
true
))
{
state
.
depth
++
;
return
helpers
.
continue
(
"
tag
"
,
"
startTag
"
);
}
return
ret
(
"
tag
"
,
"
tag
"
);
}
}
function
inAttribute
(
quote
)
{
return
function
(
stream
,
state
)
{
while
(
!
stream
.
eol
())
{
if
(
stream
.
next
()
==
quote
)
{
state
.
tokenize
=
inSmarty
;
break
;
var
ch
=
stream
.
next
();
if
(
ch
==
"
$
"
)
{
stream
.
eatWhile
(
regs
.
validIdentifier
);
return
helpers
.
continue
(
"
variable-2
"
,
"
variable
"
);
}
else
if
(
ch
==
"
.
"
)
{
return
helpers
.
continue
(
"
operator
"
,
"
property
"
);
}
else
if
(
regs
.
stringChar
.
test
(
ch
))
{
state
.
tokenize
=
parsers
.
inAttribute
(
ch
);
return
helpers
.
continue
(
"
string
"
,
"
string
"
);
}
else
if
(
regs
.
operatorChars
.
test
(
ch
))
{
stream
.
eatWhile
(
regs
.
operatorChars
);
return
helpers
.
continue
(
"
operator
"
,
"
operator
"
);
}
else
if
(
ch
==
"
[
"
||
ch
==
"
]
"
)
{
return
helpers
.
continue
(
"
bracket
"
,
"
bracket
"
);
}
else
if
(
/
\d
/
.
test
(
ch
))
{
stream
.
eatWhile
(
/
\d
/
);
return
helpers
.
continue
(
"
number
"
,
"
number
"
);
}
else
{
if
(
state
.
last
==
"
variable
"
)
{
if
(
ch
==
"
@
"
)
{
stream
.
eatWhile
(
regs
.
validIdentifier
);
return
helpers
.
continue
(
"
property
"
,
"
property
"
);
}
else
if
(
ch
==
"
|
"
)
{
stream
.
eatWhile
(
regs
.
validIdentifier
);
return
helpers
.
continue
(
"
qualifier
"
,
"
modifier
"
);
}
}
else
if
(
state
.
last
==
"
whitespace
"
)
{
stream
.
eatWhile
(
regs
.
validIdentifier
);
return
helpers
.
continue
(
"
attribute
"
,
"
modifier
"
);
}
if
(
state
.
last
==
"
property
"
)
{
stream
.
eatWhile
(
regs
.
validIdentifier
);
return
helpers
.
continue
(
"
property
"
,
null
);
}
else
if
(
/
\s
/
.
test
(
ch
))
{
last
=
"
whitespace
"
;
return
null
;
}
}
return
"
string
"
;
};
}
function
inBlock
(
style
,
terminator
)
{
return
function
(
stream
,
state
)
{
while
(
!
stream
.
eol
())
{
if
(
stream
.
match
(
terminator
))
{
state
.
tokenize
=
tokenizer
;
break
;
var
str
=
""
;
if
(
ch
!=
"
/
"
)
{
str
+=
ch
;
}
stream
.
next
();
var
c
=
null
;
while
(
c
=
stream
.
eat
(
regs
.
validIdentifier
))
{
str
+=
c
;
}
for
(
var
i
=
0
,
j
=
keyFunctions
.
length
;
i
<
j
;
i
++
)
{
if
(
keyFunctions
[
i
]
==
str
)
{
return
helpers
.
continue
(
"
keyword
"
,
"
keyword
"
);
}
}
if
(
/
\s
/
.
test
(
ch
))
{
return
null
;
}
return
helpers
.
continue
(
"
tag
"
,
"
tag
"
);
}
return
style
;
};
}
},
inAttribute
:
function
(
quote
)
{
return
function
(
stream
,
state
)
{
while
(
!
stream
.
eol
())
{
if
(
stream
.
next
()
==
quote
)
{
state
.
tokenize
=
parsers
.
smarty
;
break
;
}
}
return
"
string
"
;
};
},
inBlock
:
function
(
style
,
terminator
)
{
return
function
(
stream
,
state
)
{
while
(
!
stream
.
eol
())
{
if
(
stream
.
match
(
terminator
))
{
state
.
tokenize
=
parsers
.
tokenizer
;
break
;
}
stream
.
next
();
}
return
style
;
};
}
};
// the public API for CodeMirror
return
{
startState
:
function
()
{
return
{
tokenize
:
tokenizer
,
mode
:
"
smarty
"
,
last
:
null
};
return
{
tokenize
:
parsers
.
tokenizer
,
mode
:
"
smarty
"
,
last
:
null
,
depth
:
0
};
},
token
:
function
(
stream
,
state
)
{
var
style
=
state
.
tokenize
(
stream
,
state
);
...
...
@@ -145,4 +191,4 @@ CodeMirror.defineMode("smarty", function(config) {
};
});
CodeMirror
.
defineMIME
(
"
text/x-smarty
"
,
"
smarty
"
);
CodeMirror
.
defineMIME
(
"
text/x-smarty
"
,
"
smarty
"
);
\ No newline at end of file
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment