UNPKG

3.24 kBJavaScriptView Raw
1import { copyObj, createObj } from "./util/misc.js"
2
3// Known modes, by name and by MIME
4export 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.)
9export function defineMode(name, mode) {
10 if (arguments.length > 2)
11 mode.dependencies = Array.prototype.slice.call(arguments, 2)
12 modes[name] = mode
13}
14
15export 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.
21export 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.
40export 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.
63export let modeExtensions = {}
64export function extendMode(mode, properties) {
65 let exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {})
66 copyObj(properties, exts)
67}
68
69export 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.
83export 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
94export function startState(mode, a1, a2) {
95 return mode.startState ? mode.startState(a1, a2) : true
96}