[RFC] Generated Content proposal
This is a proposal for implementation for generated content made by @JulieBlanc in #140. I only copy pasted the content of the proposal in there so every one can see it.
String-set / string()
Sample:
@bottom-center {
content: "Running title: " string(titleBefore, first) string(title, first) string(titleAfter, first) " Attr: " string(titleAttr, first);
}
h1::before {
content: "Chapitre " counter(countChapter, upper-roman) " – ";
}
h1::after {
content: '.' ;
}
h1 {
string-set: titleBefore content(before), title content(text), titleAfter content(after), titleAttr attr(data-title);
}
1/ In content
declarations get all string()
functions (stringVar
). Ggt name (stringName
bellow) and value (stringValue
bellow) of each string()
function.
stringValue
can be:
-
first
(default), -
first-exept
, -
last
, start
// content = value of the `content`declaration
let stringFunctions = content.match(/string\((.*?)\)\s?/g);
if(stringFunctions !== null){
for(let i = 0; i < stringFunctions.length; i++){
let string = stringFunctions[i].replace(/\s?string\(/g, '').replace(/\)\s?/g, '').split(',');
let stringName = counter[0];
let stringValue;
if(counter[1] !== undefined){
stringValue = counter[1].replace(/\s/g, '');
} else {
stringValue = 'first';
}
}
}
2/ Define which node of the page is needed to build the content
with the stringValue
-
first
= the first node of the page of the element defined (ex: first<h1>
of the page) -
first-exept
= itendical tofirst
but not call on the first page where it's appear -
last
= the last node of the page of the element defined (ex: last<h1>
of the page) -
start
= if there is content on the page (ex:<p>, <li>, <dd>, <table>, <img>
...) before the element defined (ex:<h1>
), you select the last node in the previous pages of the element defined (ex: the last<h1>
of the previous page)
W3C:
first: The value of the first assignment on the page is used. If there is no assignment on the page, the ‘entry value’ is used. start: If the element is the first element on the page, the value of the first assignment is used. Otherwise the ‘entry value’ is used. The ‘entry value’ may be empty if the element hasn’t yet appeared. last: The ‘exit value’ of the named string is used. first-exept: This is identical to first, except that the empty string is used on the page where the value is assigned.
3/ In string-set
declaration get each pair separate by a ,
. A pair (StringSetVar
) is a custom identifier (stringSetName
) and a content-list (stringSetContent
)
stringSetContent
can be:
content(text)
content(before)
content(text)
content(first-letter)
attr(<identifier>)
4/ Replace each stringSetContent
by the text, attribute or generated content of the node (newStringSetContent
)
(see the file get-generated-content.js
in the branch string-set-properties
to have ::before
and ::after
content)
5/ In content
properties replace each string()
by the corresponding newStringSetContent
Something like:
if(stringVar[stringName] === StringSetVar[stringSetName]){
stringVar = newStringSetContent
}
Target-text and target-counter
Sample:
.target::before {
content: "See " target-text(attr(href), before) target-text(attr(href), content) ", p. "target-counter(attr(href), page);
}
In the same content
declaration, multiple target-text()
and target-counter()
must be possible
Ex: content: "See " target-text(attr(href), before) target-text(attr(href), content) ", p. "target-counter(attr(href), page);
Possiblilities of target-text():
target-text(attr(href), before)
target-text(attr(href), content)
target-text(attr(href), after)
target-text(attr(href), first-letter)