diff --git a/build/addons.all.js b/build/addons.all.js
index 6e32649..97cc08e 100755
--- a/build/addons.all.js
+++ b/build/addons.all.js
@@ -1,3 +1,250 @@
+
+//;(()=>{
+
+var installReceiver = function() {
+
+ let keys = new Set([
+ /* Hex is a freebie, under the special term `#` hash: #000000 */
+ // 'hex',
+ /* Color property is slightly more complicated, with the first param
+ as a forced string. */
+ // 'color',
+
+ /* Available types, each act the same way: rgb-[3 values][/A]
+ If the key is a mismatch, its ignored. */
+ 'rgb',
+ 'hsl',
+ 'hwb',
+ 'lab',
+ 'lch',
+ 'oklab',
+ 'oklch',
+ ])
+
+ ClassGraph.addons.extendedColorValues = function(cg){
+ let func = function(prop, values) {
+ return forwardHotWordReduce(prop, values, keys)
+ }
+ cg.reducers.push(func)
+ }
+}
+
+
+/* Return a boolean if the detected type is a valid css value of type:
+
+ Number: 0 | 0.0
+ Percent: 0%
+ Opacity: 0/0
+ Angle: 0turn | 0rad
+*/
+const isNumOrPerc = function(value) {
+ return isNumber(value) || isPercent(value) || isOpacityNum(value) || isAngle(value)
+}
+
+/* Return boolean for the match of a css value with an alpha: 0/0 */
+const isOpacityNum = function(value) {
+ // '60%/0.8'
+ let spl = value.split('/')
+ if(spl.length == 2) {
+ return isNumOrPerc(spl[0]) && isNumber(spl[1])
+ }
+ return false
+}
+
+const isAngle = function(value) {
+ let types = new Set(["deg","grad","rad","turn"]);
+ let extra = value.slice(parseFloat(value).toString().length, value.length)
+ return types.has(extra)
+}
+
+
+const isPercent = function(value) {
+ return value.endsWith('%') && isNumber(value.slice(0, value.length-1))
+}
+
+
+const isNumber = function(value) {
+ if(value == undefined || value.length == 0){ return false };
+ let isNum = !isNaN(Number(value))
+ return isNum
+}
+
+
+const asThreeBitColor = function(values) {
+ let ex = values.slice(4, 5)
+ let alp = ''
+ if(ex.length>0) {
+ alp = `/${ex}`
+ }
+ return `${values[0]}(${values.slice(1, 4).join(' ')}${alp})`
+}
+
+
+/* Perform a _hot word_ detection on the values recursively. A _hot word_ may be any key.
+
+ forwardHotWordReduce(
+ ['color']
+ , ['rgb', '10', '10', '10', 'eggs']
+ , new Set(['rgb'])
+ )
+
+For each forward step detect a key, if found the reducer collects as many
+forward properties as required, then releases after the first fail.
+
+This method then performs this after every release, concatenating changed and
+unchanged into a response list.
+
+ rgb-200-200-200-foo
+
+ rgb(200 200 200) foo
+
+ */
+const forwardHotWordReduce = function(props, values, keys, keyTestFunc=undefined) {
+ /*
+ Key pops early, and can accept a variable amount of vars.
+ */
+
+ let len = values.length
+ , position = 0
+ , max = values.length + 1
+ , count = 0
+ , response = []
+ ;
+
+ while(position < len && count < max) {
+ let sliced = values.slice(position)
+ let [key, usedCount] = hotWordReduce(sliced, keys, true, keyTestFunc)
+
+ position += usedCount
+ count += 1
+ if(Array.isArray(key)) {
+ response = response.concat(key)
+ } else {
+ response.push(key)
+ }
+ }
+
+ return response
+}
+
+/* Perform a _hot word_ detection on the values. A _hot word_ may be any key.
+
+ forwardHotWordReduce(
+ , ['rgb', '10', '10', '10', 'eggs']
+ , new Set(['rgb'])
+ , true
+ )
+
+ rgb(200 200 200) // break early
+ rgb(200 200 200) egg
+
+For each forward step detect a key, if found the reducer collects as many
+forward properties as required, then releases after the first fail if `breakEarly` is true.
+
+ rgb-200-200-200-foo-hsl-20-0%-10-foo
+
+ rgb(200 200 200) foo hsl(20 0% 10) foo
+
+ */
+
+const hotWordReduce = function(values, keys
+ , breakEarly=false
+ , callback=asThreeBitColor
+ , keyTestFunc=undefined) {
+
+ var i = 0;
+ let inSet = (x) => keys.has(x)
+ , keyStartMatch = keyTestFunc != undefined? keyTestFunc: inSet
+ , l = values.length
+ , bits = []
+ , kept = []
+ , lost = []
+ , max = 4 // can be 3 or 4
+ ;
+
+ for (;i < l; i++) {
+ // console.log('---')
+ let k = values[i];
+ let inI = i;
+ if(keyStartMatch(k)) {
+ // console.log(i, 'MATCH', k)
+ let j = i+1
+ kept = [k]
+ lost = []
+ let ok = true
+ while(ok && j < l) {
+ let subI = j;
+ let subK = values[subI];
+ let isNum = isNumOrPerc(subK)
+ ok = isNum && j < l && kept.length <= (max-1) // +1 for the original key
+ if(isNum) {
+ // console.log('Push', subK)
+ j += 1
+ kept.push(subK)
+ ok = ok && kept.length <= max // +1 for the original key
+ } else {
+ // Lost stack
+ // console.log('Lost stack on', subK)
+ // j = 1
+ lost.push(subK)
+ }
+ // console.log('S', subI, subK, isNum, ok)
+ }
+
+ let [a,b] = [inI, j]
+ // console.log('a,b ',a, b, values.slice(a,b), kept)
+ let plucked = kept.slice(a, b);
+ let newEntry = callback(kept)
+ if(plucked.length < 3) {
+ // console.log('Failed.', bits)
+ bits = bits.concat(kept)
+ if(breakEarly) {
+ return [bits, j]
+ }
+ } else {
+ // console.log('kept', kept, newEntry)
+ // console.log('plucked', plucked)
+ bits.push(newEntry)
+ // Push back 2, as we landed on the bad node,
+ // and we need step into this node, to stack it.
+ //
+ i = j-1
+ }
+ } else {
+ // console.log(i, k)
+ bits.push(k)
+
+ if(breakEarly) {
+ let [a,b] = [inI, kept.length]
+ // console.log('a,b ',a, b, values.slice(a,b), kept)
+ let plucked = kept.slice(a, b);
+ let newEntry = callback(kept)
+ // console.log('plucked', plucked)
+ // console.log('kept', kept)
+ if(kept.length < 3) {
+ // console.log('Failed.', 'kept', kept, 'plucked', plucked)
+ return [values[b], kept.length+1]
+ } else {
+ // console.log('success.')
+ return [newEntry, kept.length]
+ }
+
+ return [values[0], 1]
+ }
+ }
+ }
+
+ // console.log('Done pop', i)
+ // console.log('in', values, 'out', bits)
+
+ let newEntry = callback(kept)
+ return [newEntry, i+1]
+}
+
+
+;installReceiver();
+
+// })()
/**
* # Events event-[eventName]-[action]-[params]*
*
@@ -150,6 +397,8 @@
cg = _cg;
cg.insertReceiver(['font', 'pack'], fontPackReceiver)
}
+ ClassGraph.prototype.generateGoogleLinks = generateGoogleLinks
+ ClassGraph.prototype.installGoogleLinks = installGoogleLinks
}
/**
@@ -172,15 +421,18 @@
let familyStrings = createFamilyString(values, fonts, origin)
// let families = tokenize(values)
-
- // install as header items
- // console.info('Installing Google fonts: familyStrings:', familyStrings)
- generateGoogleLinks(familyStrings).forEach((x)=>document.head.appendChild(x))
+ installGoogleLinks(familyStrings)
// Install additional css additions
installFontObjects(fonts, obj)
}
+ const installGoogleLinks = function(familyStrings, display) {
+ // install as header items
+ // console.info('Installing Google fonts: familyStrings:', familyStrings)
+ return generateGoogleLinks(familyStrings, display).forEach((x)=>document.head.appendChild(x))
+ }
+
const installFontObjects = function(fonts, splitObj) {
// // For value create a font-family;
@@ -544,7 +796,7 @@
})
}
- const generateGoogleLinks = function(familyStrings){
+ const generateGoogleLinks = function(familyStrings, display='swap'){
let a = getOrCreateLink('link', 'preconnect', {
href: "https://fonts.googleapis.com"
@@ -555,8 +807,10 @@
, crossorigin: ''
})
+ let ds = display == null? '': `&display=${display}`
+
let c = getOrCreateLink('link', "stylesheet", {
- href:`https://fonts.googleapis.com/css2?${familyStrings}&display=swap`
+ href:`https://fonts.googleapis.com/css2?${familyStrings}${ds}`
})
return [a,b,c]
@@ -564,6 +818,18 @@
let linkCache = {}
+ /*
+ Create a link node
+
+ let b = getOrCreateLink('link', 'preconnect', {
+ href: "https://fonts.gstatic.com"
+ , crossorigin: ''
+ })
+
+ let c = getOrCreateLink('link', "stylesheet", {
+ href:`https://fonts.googleapis.com/css2?${familyStrings}&display=swap`
+ })
+ */
const getOrCreateLink = function(href, rel, opts) {
let v = {
rel, href
@@ -600,6 +866,365 @@
})()
+;(function(){
+
+ let cg;
+ let rootDeclaration = {};
+ let definition = undefined
+ let rootRule;
+
+ const insertReceiver = function(){
+
+ ClassGraph.addons.functionsReceiver = function(_cg){
+ cg = _cg;
+ cg.keyValueFunctions.set('forceGreen', forceHook)
+ cg.keyValueFunctions.set('force', forceHook)
+ cg.keyValueFunctions.set('raise', raiseHook)
+ }
+ }
+
+ const forceHook = function(value, token, index, splitObj) {
+ // console.log('Force green hook', token, splitObj)
+ let res = token.value.slice(0, token.match.start)
+ // console.log(res)
+ // return res
+
+ return token.args.length > 0? token.args[0]: 'green'
+ }
+
+ const raiseHook = function(value, token, index, splitObj) {
+ console.log('raise hook', token, splitObj)
+ let res = token.value.slice(0, token.match.start)
+ console.log(res)
+ // return res
+ }
+
+ const functionsHook = function(d) {
+
+ // target = document.querySelector(target)
+ console.log('functions', d)
+ }
+
+
+ ;insertReceiver();
+})()
+
+class PolyclassIcons {
+
+}
+
+;(function(){
+
+ let cg;
+ const insertReceiver = function(){
+
+ ClassGraph.addons.iconReceiver = function(_cg){
+ cg = _cg;
+
+ // Capture a single key
+ // cg.insertTranslator('var', variableDigest2)
+ cg.insertReceiver(['icon', 'pack'], iconPackReceiver)
+ // cg.insertReceiver(['icon'], iconReceiver)
+ }
+ }
+
+ const titleCase = (words) => words.map(function(word) {
+ return word.charAt(0).toUpperCase() + word.substring(1, word.length);
+ });
+
+ const iconPackReceiver = function(obj) {
+
+ let key = titleCase(obj.values).join('+')
+ let family = `Material+Symbols+${key}`
+ let defaultFontSettings = {
+ FILL: 1,
+ wght: 500,
+ GRAD: 200,
+ opsz: 48
+ }
+ /* Options for the _variable font_ These don't change.*/
+ let opts= {
+ opsz: "20..48",
+ wght: "100..700",
+ FILL: "0..1",
+ GRAD: "-50..200",
+ }
+ let familyString = toGoogleFontParamsStr(opts)
+ let fontStr = `family=${family}:${familyString}`
+
+ let receiverBits = [...obj.values, 'icon']
+
+ /* Install a new class, capturing: `[variant]-icon-*`
+ The variant is the _style_ of icon, such as "outlined" or "sharp". */
+ cg.insertReceiver(receiverBits, iconReceiver)
+
+
+ /*Leverage the font installer, using the fonter and the name given.*/
+ Polyclass.graph.installGoogleLinks(fontStr, null)
+
+ /* Install the css class rule object */
+ installSheetRules(obj, fontSettings)
+
+ // let opts = `opsz,wght,FILL,GRAD
+ // @20..48,100..700,0..1,-50..200`
+ //
+ // let example = `https://fonts.googleapis.com/css2?
+ // family=Material+Symbols+Outlined:
+ // opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200`
+ //
+ }
+
+ const installSheetRules = function(obj, fontSettings){
+ /*.material-symbols-sharp {
+ font-variation-settings:
+ 'FILL' 0,
+ 'wght' 500,
+ 'GRAD' 200,
+ 'opsz' 48;
+ font-size: inherit;
+ }*/
+ let key = obj.values[0]
+ let rules = {}
+
+ let fontSettingsStr = toObjectParamStr(fontSettings)
+ let conf = {
+ 'font-variation-settings': `${fontSettingsStr}`,
+ 'font-size': 'inherit',
+ }
+
+ rules[`.material-symbols-${key}`] = conf
+ let items = cg.dcss.addStylesheetRules(rules)
+
+ items.renderAll()
+ }
+
+ const toObjectParamStr = function(obj) {
+ /*Given an object, convert it to a string, compatible with an object-like
+ CSS String:
+
+ {
+ FILL: 1,
+ wght: 500,
+ GRAD: 200,
+ opsz: 48
+ }
+
+ Return a multiline string, with the properties string wrapped:
+
+ 'FILL' 1,
+ 'wght' 500,
+ 'GRAD' 200,
+ 'opsz' 48
+ */
+ let fontSettingsStr = '';
+ let fKeys = Object.keys(obj)
+ for (var i = 0; i < fKeys.length; i++) {
+ let k = fKeys[i]
+ let v = obj[k]
+ let last = i == fKeys.length-1
+ let end = last? '': ',\n'
+ fontSettingsStr += `'${k}' ${v}${end}`
+ }
+ return fontSettingsStr
+
+ }
+
+ const toGoogleFontParamsStr = function(obj) {
+ /* Given an object, convert to a string compatible with the google font
+ in = {
+ opsz: "20..48",
+ wght: "100..,700",
+ FILL: "0..1",
+ GRAD: "-50..200",
+ }
+
+ out = `opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200`
+ */
+ let k = Object.keys(obj).join(',')
+ let v = Object.values(obj).join(',')
+ return `${k}@${v}`
+ }
+
+ const iconReceiver = function(obj) {
+
+ // Tokenize as a family string.
+ //
+ const values = obj.values, origin = obj.origin;
+ console.log('render icon', obj)
+
+ return contentInjection(obj)
+ }
+
+ const contentInjection = function(obj) {
+ const values = obj.values, origin = obj.origin;
+ origin.classList.add(getInjectClass(obj))
+ origin.innerText += `${values.join('_')}`
+ }
+
+ const getInjectClass = function(obj) {
+ let k = obj.props[0]
+ return `material-symbols-${k}`
+ }
+
+ ;insertReceiver();
+})()
+
+;(function(){
+
+ let cg;
+ const insertReceiver = function(){
+
+ ClassGraph.addons.iconReceiver = function(_cg){
+ cg = _cg;
+
+ // Capture a single key
+ // cg.insertTranslator('var', variableDigest2)
+ cg.insertReceiver(['icon', 'pack'], iconPackReceiver)
+ // cg.insertReceiver(['icon'], iconReceiver)
+ }
+ }
+
+ const titleCase = (words) => words.map(function(word) {
+ return word.charAt(0).toUpperCase() + word.substring(1, word.length);
+ });
+
+ const iconPackReceiver = function(obj) {
+ console.log('Install the font', obj)
+ let key = titleCase(obj.values).join('+')
+ let family = `Material+Symbols+${key}`
+ let fontSettings = {
+ FILL: 1,
+ wght: 500,
+ GRAD: 200,
+ opsz: 48
+ }
+ /* Options for the _variable font_ These don't change.*/
+ let opts= {
+ opsz: "20..48",
+ wght: "100..700",
+ FILL: "0..1",
+ GRAD: "-50..200",
+ }
+ let familyString = toGoogleFontParamsStr(opts)
+ let fontStr = `family=${family}:${familyString}`
+
+ let receiverBits = [...obj.values, 'icon']
+
+ /* Install a new class, capturing: `[variant]-icon-*`
+ The variant is the _style_ of icon, such as "outlined" or "sharp". */
+ cg.insertReceiver(receiverBits, iconReceiver)
+
+
+ /*Leverage the font installer, using the fonter and the name given.*/
+ Polyclass.graph.installGoogleLinks(fontStr, null)
+
+ /* Install the css class rule object */
+ installSheetRules(obj, fontSettings)
+
+ // let opts = `opsz,wght,FILL,GRAD
+ // @20..48,100..700,0..1,-50..200`
+ //
+ // let example = `https://fonts.googleapis.com/css2?
+ // family=Material+Symbols+Outlined:
+ // opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200`
+ //
+ }
+
+ const installSheetRules = function(obj, fontSettings){
+ /*.material-symbols-sharp {
+ font-variation-settings:
+ 'FILL' 0,
+ 'wght' 500,
+ 'GRAD' 200,
+ 'opsz' 48;
+ font-size: inherit;
+ }*/
+ let key = obj.values[0]
+ let rules = {}
+
+ let fontSettingsStr = toObjectParamStr(fontSettings)
+ let conf = {
+ 'font-variation-settings': `${fontSettingsStr}`,
+ 'font-size': 'inherit',
+ }
+
+ rules[`.material-symbols-${key}`] = conf
+ let items = cg.dcss.addStylesheetRules(rules)
+
+ items.renderAll()
+ }
+
+ const toObjectParamStr = function(obj) {
+ /*Given an object, convert it to a string, compatible with an object-like
+ CSS String:
+
+ {
+ FILL: 1,
+ wght: 500,
+ GRAD: 200,
+ opsz: 48
+ }
+
+ Return a multiline string, with the properties string wrapped:
+
+ 'FILL' 1,
+ 'wght' 500,
+ 'GRAD' 200,
+ 'opsz' 48
+ */
+ let fontSettingsStr = '';
+ let fKeys = Object.keys(obj)
+ for (var i = 0; i < fKeys.length; i++) {
+ let k = fKeys[i]
+ let v = obj[k]
+ let last = i == fKeys.length-1
+ let end = last? '': ',\n'
+ fontSettingsStr += `'${k}' ${v}${end}`
+ }
+ return fontSettingsStr
+
+ }
+
+ const toGoogleFontParamsStr = function(obj) {
+ /* Given an object, convert to a string compatible with the google font
+ in = {
+ opsz: "20..48",
+ wght: "100..,700",
+ FILL: "0..1",
+ GRAD: "-50..200",
+ }
+
+ out = `opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200`
+ */
+ let k = Object.keys(obj).join(',')
+ let v = Object.values(obj).join(',')
+ return `${k}@${v}`
+ }
+
+ const iconReceiver = function(obj) {
+
+ // Tokenize as a family string.
+ //
+ const values = obj.values, origin = obj.origin;
+ console.log('render icon', obj)
+
+ return contentInjection(obj)
+ }
+
+ const contentInjection = function(obj) {
+ const values = obj.values, origin = obj.origin;
+ origin.classList.add(getInjectClass(obj))
+ origin.innerText += `${values.join('_')}`
+ }
+
+ const getInjectClass = function(obj) {
+ let k = obj.props[0]
+ return `material-symbols-${k}`
+ }
+
+ ;insertReceiver();
+})()
+
/**
* # Monitor
*
@@ -705,274 +1330,34 @@ const difference = function(setA, setB) {
})()
/*
+Convert discovered nodes and bind them to a selector. The assigned classes
+are the declarations assigned to the css class.
-vars box. To assign key variables as accessible CSS varialbes through a js
-definition. The definition is bound to DCSS, so edits to the vars manipulates
-the view automatically.
+The discovery may descend children, allowing for depth setup.
- vars({
- primary: "#880000" # company red
- , secondary: "#111" # dark
- , accent: "red"
- })
+ An elk called Elk lives here.
An elk called Elk lives here.
+An elk called Elk lives here.
-An elk called Elk lives here.
+An elk called Elk lives here.
-An elk called Elk lives here.
+An elk called Elk lives here.
-An elk called Elk lives here.
+An elk called Elk lives here.
-An elk called Elk lives here.
+An elk called Elk lives here.
-An elk called Elk lives here.
+Is a library class, populated with properties governed by the flavour
+