- let scriptUsed = false; - const varObjects = { repeatingSectionDetails:[], actionAttributes:[], cascades:{ attr_character_name:{ name:'character_name', type:'text', defaultValue:'', affects:[], triggeredFuncs:['setActionCalls'], listenerFunc:'accessSheet', listener:'change:character_name'} } }; - let repeatingPrefix = ''; - let repeatsIgnoreSystemPrefix = false; - let systemPrefix = ''; - let variables = ""; variables += `arguments.callee -> ${arguments.callee}\n`; //variables += `pug_debug_filename -> ${pug_debug_filename}\n`; // variables += `pug -> ${pug}\n`; // variables += `fs -> ${fs}\n`; // throw new Error(variables); - const checkKUse = () => { if(scriptUsed){ throw Error('kScript mixin already used. Kscript should be the final mixin used in the sheet code.'); } }; - const getSystemPrefix = () => systemPrefix || ''; //- @pugdoc name: SetSystemPrefix description: Updates the systemPrefix K-scaffold global variable so that any attributes created after this point will be prepended with the prefix. By default attributes in repeating sections are not prepended; instead the repeating section name is prefixed. Returns the previous prefix. arguments: - {string} val - The value to set the prefix to. If not a string or falsy, will reset the prefix to an empty string. - {boolean} [normalRepeating = true] - Whether the prefix should be applied to repeating section names (default), or to the attribute name itself in repeating sections. attributes: example: | include _htmlelements.pug // Non repeating attributes setSystemPrefix('npc') +number({name:'athletics',value:0}) // pass it a falsy value to unset it setSystemPrefix(false) +number({name:'athletics',value:0}) // Repeating attributes setSystemPrefix('npc') +fieldset({name:'skill'}) +number({name:'score',value:0}) - const setSystemPrefix = (val,normalRepeating = false) => { repeatsIgnoreSystemPrefix = normalRepeating; const prevPrefix = systemPrefix; systemPrefix = typeof val === 'string' ? val : ''; return prevPrefix; }; //- @pugdoc name: attrTitle description: Converts an attribute name into an attribute call for that attribute. Converts `_max` attribute names to the proper attribute call syntax for `_max` attributes (see second example). If called from inside the block of a {@link fieldset} mixin, will also add the appropriate information for calling a repeating attribute. arguments: - {string} attrName - The attribute name to create an attribute call for. attributes: example: | include _htmlelements.pug //Basic attribute name +input({name:'hidden name',type:'text',title:attrTitle('user accessible name')}) //Max attribute name +input({name:'hidden max',type:'number',title:attrTitle('user accessible max')}) //fieldset attrTitle +fieldset({name:'equipment'}) +input({name:'name',type:'text',title:attrTitle('user accessible name')}) - const attrTitle = (string) => `@{${repeatingPrefix}${replaceSpaces(string).replace(/_max$/,'|max')}}`; - const attrName = (string) => { const sp = getSystemPrefix(); let tempString = replaceSpaces(`${ (repeatingPrefix && !repeatsIgnoreSystemPrefix) || !sp || /^character[\s_]name$/.test(string) ? '' : `${sp} ` }${string}`); if(sp){ tempString = tempString .replace(new RegExp(`${sp}[_-]${sp}`),sp); } return tempString; }; //- @pugdoc name: buttonTitle description: Converts an ability name into an ability call for that attribute. If called from inside the block of a {@link fieldset} mixin, will also add the appropriate information for calling a repeating attribute. arguments: - {string} abilityName - The ability name to create a call for. attributes: example: | include _htmlelements.pug //Basic button title +button({name:'hidden button',type:'text',title:buttonTitle('user accessible name')}) //fieldset button title +fieldset({name:'equipment'}) +button({name:'button',type:'text',title:buttonTitle('user accessible name')}) - const buttonTitle = (string) => `%{${repeatingPrefix}${replaceSpaces(string)}}`; //- @pugdoc name: replaceSpaces description: Replaces spaces in a string with underscores (`_`). arguments: - {string} string - The string to work on attributes: - const replaceSpaces = (string) => string.replace(/\s+/g,'_'); //- @pugdoc name: replaceProblems description: Escapes problem characters in a string for use as a regex. arguments: - {string} string - The string to work on attributes: - const replaceProblems = (string) => string.replace(/[\(\)\[\]\|\/\\]/g,'-'); //- @pugdoc name: capitalize description: Capitalizes the first let of words in a string. arguments: - {string} string - The string to work on attributes: - const capitalize = (string)=> string.replace(/(?:^|\s+|\/)[a-z]/ig,(letter)=>letter.toUpperCase()); - const actionButtonName = (name) => `${name.replace(/_|\s+/g,'-')}`; - const actionInputName = (name) => `${name}_action`.replace(/roll_action/,'action'); - const titleToName = (string) => string.replace(/[@%]\{|\}/g,''); - const addIfUnique = (item,arrName) => { varObjects[arrName] = varObjects[arrName] || []; if(varObjects[arrName].indexOf(item) === -1){ varObjects[arrName].push(item); } }; - const storeTrigger = function(element){ let trigger = element.trigger || {}; const namePrefix = { roll:'roll_', action:'act_', fieldset:'fieldset_' }; const typeDefs = { select:'', radio:0, checkbox:0, number:0, text:'', span:'' }; const eventTypes = { roll:'clicked', action:'clicked', fieldset:'remove' }; let elementName = element.title ? titleToName(element.title) : element.name; trigger.name = elementName.replace(/\|/g,'_'); let cascName = `${namePrefix[element.type] || 'attr_'}${trigger.name}`; let match = trigger.name.match(/(repeating_[^_]+)_[^_]+_(.+)/); let [,section,field] = match || [,,trigger.name]; let eventType = eventTypes[element.type] || 'change'; if(!varObjects.cascades[cascName]){ if(trigger.listener || trigger.triggeredFuncs || trigger.listenerFunc || trigger.initialFunc || trigger.affects){ trigger.listener = trigger.listener || `${eventType}:${section ? `${section}:` : ''}${field}`; trigger.listenerFunc = trigger.listenerFunc || 'accessSheet'; } trigger.type = element.type; if(!namePrefix[element.type]){ trigger.defaultValue = trigger.hasOwnProperty('defaultValue') ? trigger.defaultValue : (element.type === 'checkbox' && !element.hasOwnProperty('checked')) ? 0 : element.hasOwnProperty('value') ? element.value : typeDefs.hasOwnProperty(element.type) ? typeDefs[element.type] : ''; trigger.triggeredFuncs = trigger.triggeredFuncs || []; if(trigger.affects){ trigger.affects = trigger.affects.map((affect)=>{ const attributeName = attrName(affect); return replaceSpaces(attributeName) }); }else{ trigger.affects = []; } } varObjects.cascades[cascName] = {...trigger}; }else{ if(!namePrefix[varObjects.cascades[cascName].type]){ varObjects.cascades[cascName].triggeredFuncs = trigger.triggeredFuncs ? [...new Set([...varObjects.cascades[cascName].triggeredFuncs,...trigger.triggeredFuncs])] : varObjects.cascades[cascName].triggeredFuncs; varObjects.cascades[cascName].affects = trigger.affects ? [...new Set([...varObjects.cascades[cascName].affects,...trigger.affects])] : varObjects.cascades[cascName].affects; varObjects.cascades[cascName].calculation = varObjects.cascades[cascName].calculation || trigger.calculation; } if(trigger.listenerFunc || trigger.triggeredFuncs || trigger.affects){ varObjects.cascades[cascName].listener = varObjects.cascades[cascName].listener || trigger.listener || `${eventType}:${section ? `${section}:` : ''}${field}`; varObjects.cascades[cascName].listenerFunc = varObjects.cascades[cascName].listenerFunc || trigger.listenerFunc || 'accessSheet'; } } }; - const getSectionDetails = function(section){ return varObjects.repeatingSectionDetails.find((obj)=>obj.section === section); }; - const createFieldsetObj = function(section){ !getSectionDetails(section) ? varObjects.repeatingSectionDetails.push({section,fields:[]}) : null; }; - const addFieldToFieldsetObj = function(obj){ let section = repeatingPrefix.replace(/_[^_]+_$/,''); let sectionDetails = getSectionDetails(section); let name = obj.name.replace(/^attr_/,''); if(sectionDetails && sectionDetails.fields.indexOf(name) < 0){ sectionDetails.fields.push(name); } }; - const makeElementObj = function(obj){ const newObj = {...obj}; delete newObj.trigger; return newObj; };