Punctuation Modifiers
Funcdown utilizes some of the prefix and suffix characters. So called prefix and suffix modifiers. In order for one to apply suffix or prefix character, single white space (if suffix - before; if prefix - after) plays very important role. That one single space is what makes it work. Just like bash (shell) syntax. There are few of those characters, and here they are:
-
Exclamation modifier
It is suffix-only modifier and works for both attribute values and text node values and its role is to force xml decimal entity encoding, but, in some cases using this modifier is uneccessary, as it is already - enforced. Anyway, this ...
p {<script></script> !}
... will render the following:<p><script></script></p>
While without it ..p {<script></script>}
You would get what You would expect, something like this ..<p><script></script></p>
The same goes for the attribute values. This (note the T (type) attribute value) ...L (rel stylesheet, T text/css !, media all, % /style.css)|
.. will render the following:<link rel="stylesheet" type="text/css" media="all" href="/style.css">
-
Circumflex Accent modifier
C.Accent
^
is suffix-only character and does the opposite of!
. It decodes xml decimal entities back to their real characters. This modifier is for predefind tags and attributes. It simply won't have effect anywhere else. If we would like to display a portion of JS code within let's saypre
tag, but to leave all problematic punctuation characters intact, this will do.pre {:>>> ((Language) => { console.info(Language); }) ('Javascript'); ^ <<<:}
Note how^
is not right next to the closingsafestring
wrapper but has one white space after. For regular
white spaces do not play special role with curly wrappers as they do withcode {Fun(c down) { string \} ^}
.pre {:>>> Fun(c down,safe) { string } ^ <<<:}
-
Percent Sign modifier
Percent sign
%
is a suffix modifier for the attribute data and prefix modifier for string node data. When placed after attribute value, it will urlencode the attribute value, unless attribute is not one of the mentioned in enforced rules. Something like this (note the src attribute value) ..J(src /?mice=%jsdata %,T text/javascript){}
Will render (% is turned into %25) ..<script src="/?mice=%25jsdata" type="text/javascript"></script>
When used before string (right after opening wrapper and a blank space), it will force raw source code identation properly to the left-side, which is quite neat for preformatted source code representation (pre or code tags). Example method taken from the funcdown library ..pre {:>>> % private function parse_fncd_array (array $array) { /// Funcdown array (PHP-native) govern/parse action. $this-> parse_fncd_string ($this-> atos ($array)); } <<<:}
.. will be rendered like this: (note the identation, default 2 spaces)<pre> private function parse_fncd_array (array $array) { /// Funcdown array (PHP-native) govern/parse action. $this-> parse_fncd_string ($this-> atos ($array)); } </pre>
For the record, this ENTIRE text (the whole rendered html page) with monospaced font is aligned to the left because of prefix%
utilization. You may want to test that out on playground .. ? Default identation (starting left point) is 2 spaces.ident_eol
is stall configuration property where You can tune it, and You can test that out only locally.Aligning text with percent sign (as prefix modifier) won't work for Microdown syntax. Due to Microdown nature, which is invented specifically for inline html tags, it is not logical to wrap huge text data with (although one can do it) and to expect preformatted and properly aligned multi-line portions of text.
-
Asterisk and Quote modifiers
Those three are attribute only, prefix only modifiers and their purpose is to make attribute values - naked or to make them wrapped with single or double quotes. Hence there's difference where no single space plays important role with these modifiers. These three must be GLUED from the left side to the value.
quotes_only
stall configuration property, toggled to true will force all attribute values to be wrapped with double-quotes, which is most common case scenario. But, some folks prefer to write single-phrase html attribute values without quotes, which is valid in case of html5, as long as there are no white spaces involved. In case of quotes_only value is set to default 1 and we want ourmeta charset
without quotes, this will do ..M(charset *utf-8)|
It will render:<meta charset=utf-8>
Now, let's imagine that quotes_only parameter is 0 / false. This (note the apostrophe'
after@
) ...M(N description,@ 'This is page description text)|
.. will render:<meta name=description content='This is page description text'>
The same would happen with double-quote"
with quotes_only - off or false. Value for thename
attribute would remain - naked, andcontent
value would be wrapped with double-quotes. Conclusion ?'
- Apostrophe or single-quote mark - always makes change.*
- Asterisk will make changes when quotes_only is set to 1 or true"
- Double-Quote mark will make changes only when quotes_only is set to 0 or false -
Grave Accent
This character does not play special role in native Funcdown string context, but has some other, very unique feature. It is utilized in certain cases for when Fundown is provided in Hashmap mode for fragment inclusion. It is also used in Microdown syntax in order to distiguish which attribute will go to which tag, when there is certain textnode wrapped with more than one tag.
-
Side Notes
Beside roles that asterisk, percent and exclamation (
*
,%
and!
) characters have in this context, those three also serve as shorthands as stated in the Expansion Tables, and here is quick reminder below:-
%
is also a shorthand substitute for the href attribute, eg:a (% https://website.com) {Link Name}
-
!
is also a shorthand for title attribute (instead oftitle My Title
->! My Title
) and its main role is for opening HTML Comment, eg:!{Comment}
-
*
plays a role for primary DTD tag, eg:*{5}
(for html5 documents) or*{X}
(for XML documents)
Enforced Rules
-
Funcdown will encode dangerous characters automatically for the following:
-
Values for predefined attributes
,alt
,title
andplaceholder
defined indata-before
PrConst::ATP
hashmap -
DIRECT textnodes for prefeined
,pre
andcode
tags defined intextarea
PrConst::FORMAT_BYPASS
hashmap -
Each textnode within microdown syntax and just some microdown attribute values as in list item 1.
- Using
!
as suffix after predefined attribute value: expect double-encoding result.- Using
!
as suffix after predefined tag textnode: expect no change with!
swallowed
.- Using
!
as suffix after microdown textnode: expect as is with!
intact.It is worth mentioning that predefined attributes will not accept
%
suffix modifier,
meaning only^
suffix modifier - will always work, will revert string back to normal, for all three cases. -
One may want to take a look at Funcdown library file for the PrConst trait for more details, and eventually expand the tag names there.
Expanding default language attribute list is a bit more complicated and requires more deeper editing and understanding, thus - not recommended.
However, if there are strong reqiurements for doing so, here are the steps needed for expansion:
-
Find
private const ATP
hashmap (the firstconst
inPrConst
trait) and add desired attribute name. -
In the same trait, find
L_MARKS
hashmapconst
and add new C-OCTAL escaped key/index with proper value. This key should be very, very unique. Something that will clearly distinguish it from others. If You have added lets sayaria-label
in the first step, the value should be'al'
, something like that. By looking at other elements (and comments) inside that hashmap, You will get the idea. DO NOT - add it in between, but make the key after already predefined items. -
After You have determined which key and value is appropriate for Your new special attribute defined in
ATP
hashmap, findfilter_whitelisted_attributes
method inside trait calledNative
. There's amatch
control structure inside
that looks something like this:[$key, $twin] = match ($attribute_name) { self::ATP[0] => [$lmvals[4], $lmkeys[4]], self::ATP[1] => [$lmvals[5], $lmkeys[5]], self::ATP[2] => [$lmvals[6], $lmkeys[6]], self::ATP[3] => [$lmvals[7], $lmkeys[7]], default => ['',''] };
Simply add one more case and that should do.
Something like this:[$key, $twin] = match ($attribute_name) { self::ATP[0] => [$lmvals[4], $lmkeys[4]], self::ATP[1] => [$lmvals[5], $lmkeys[5]], self::ATP[2] => [$lmvals[6], $lmkeys[6]], self::ATP[3] => [$lmvals[7], $lmkeys[7]],
self::ATP[4] => [$lmvals[8], $lmkeys[8]],
default => ['',''] };
-