modes.min.js (3241B)
1 import { copyObj, createObj } from "./util/misc.js" 2 3 // Known modes, by name and by MIME 4 export let modes = {}, mimeModes = {} 5 6 // Extra arguments are stored as the mode's dependencies, which is 7 // used by (legacy) mechanisms like loadmode.js to automatically 8 // load a mode. (Preferred mechanism is the require/define calls.) 9 export function defineMode(name, mode) { 10 if (arguments.length > 2) 11 mode.dependencies = Array.prototype.slice.call(arguments, 2) 12 modes[name] = mode 13 } 14 15 export function defineMIME(mime, spec) { 16 mimeModes[mime] = spec 17 } 18 19 // Given a MIME type, a {name, ...options} config object, or a name 20 // string, return a mode config object. 21 export function resolveMode(spec) { 22 if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { 23 spec = mimeModes[spec] 24 } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { 25 let found = mimeModes[spec.name] 26 if (typeof found == "string") found = {name: found} 27 spec = createObj(found, spec) 28 spec.name = found.name 29 } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) { 30 return resolveMode("application/xml") 31 } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) { 32 return resolveMode("application/json") 33 } 34 if (typeof spec == "string") return {name: spec} 35 else return spec || {name: "null"} 36 } 37 38 // Given a mode spec (anything that resolveMode accepts), find and 39 // initialize an actual mode object. 40 export function getMode(options, spec) { 41 spec = resolveMode(spec) 42 let mfactory = modes[spec.name] 43 if (!mfactory) return getMode(options, "text/plain") 44 let modeObj = mfactory(options, spec) 45 if (modeExtensions.hasOwnProperty(spec.name)) { 46 let exts = modeExtensions[spec.name] 47 for (let prop in exts) { 48 if (!exts.hasOwnProperty(prop)) continue 49 if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop] 50 modeObj[prop] = exts[prop] 51 } 52 } 53 modeObj.name = spec.name 54 if (spec.helperType) modeObj.helperType = spec.helperType 55 if (spec.modeProps) for (let prop in spec.modeProps) 56 modeObj[prop] = spec.modeProps[prop] 57 58 return modeObj 59 } 60 61 // This can be used to attach properties to mode objects from 62 // outside the actual mode definition. 63 export let modeExtensions = {} 64 export function extendMode(mode, properties) { 65 let exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {}) 66 copyObj(properties, exts) 67 } 68 69 export function copyState(mode, state) { 70 if (state === true) return state 71 if (mode.copyState) return mode.copyState(state) 72 let nstate = {} 73 for (let n in state) { 74 let val = state[n] 75 if (val instanceof Array) val = val.concat([]) 76 nstate[n] = val 77 } 78 return nstate 79 } 80 81 // Given a mode and a state (for that mode), find the inner mode and 82 // state at the position that the state refers to. 83 export function innerMode(mode, state) { 84 let info 85 while (mode.innerMode) { 86 info = mode.innerMode(state) 87 if (!info || info.mode == mode) break 88 state = info.state 89 mode = info.mode 90 } 91 return info || {mode: mode, state: state} 92 } 93 94 export function startState(mode, a1, a2) { 95 return mode.startState ? mode.startState(a1, a2) : true 96 }