Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/gohugoio/hugo-mod-jslibs-dist.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'alpinejs/packages/alpinejs/src/directives.js')
-rw-r--r--alpinejs/packages/alpinejs/src/directives.js188
1 files changed, 188 insertions, 0 deletions
diff --git a/alpinejs/packages/alpinejs/src/directives.js b/alpinejs/packages/alpinejs/src/directives.js
new file mode 100644
index 0000000..42d1654
--- /dev/null
+++ b/alpinejs/packages/alpinejs/src/directives.js
@@ -0,0 +1,188 @@
+import { onAttributeRemoved, onElRemoved } from './mutation'
+import { evaluate, evaluateLater } from './evaluator'
+import { elementBoundEffect } from './reactivity'
+import Alpine from './alpine'
+
+let prefixAsString = 'x-'
+
+export function prefix(subject = '') {
+ return prefixAsString + subject
+}
+
+export function setPrefix(newPrefix) {
+ prefixAsString = newPrefix
+}
+
+let directiveHandlers = {}
+
+export function directive(name, callback) {
+ directiveHandlers[name] = callback
+}
+
+export function directives(el, attributes, originalAttributeOverride) {
+ let transformedAttributeMap = {}
+
+ let directives = Array.from(attributes)
+ .map(toTransformedAttributes((newName, oldName) => transformedAttributeMap[newName] = oldName))
+ .filter(outNonAlpineAttributes)
+ .map(toParsedDirectives(transformedAttributeMap, originalAttributeOverride))
+ .sort(byPriority)
+
+ return directives.map(directive => {
+ return getDirectiveHandler(el, directive)
+ })
+}
+
+export function attributesOnly(attributes) {
+ return Array.from(attributes)
+ .map(toTransformedAttributes())
+ .filter(attr => ! outNonAlpineAttributes(attr))
+}
+
+let isDeferringHandlers = false
+let directiveHandlerStacks = new Map
+let currentHandlerStackKey = Symbol()
+
+export function deferHandlingDirectives(callback) {
+ isDeferringHandlers = true
+
+ let key = Symbol()
+
+ currentHandlerStackKey = key
+
+ directiveHandlerStacks.set(key, [])
+
+ let flushHandlers = () => {
+ while (directiveHandlerStacks.get(key).length) directiveHandlerStacks.get(key).shift()()
+
+ directiveHandlerStacks.delete(key)
+ }
+
+ let stopDeferring = () => { isDeferringHandlers = false; flushHandlers() }
+
+ callback(flushHandlers)
+
+ stopDeferring()
+}
+
+export function getElementBoundUtilities(el) {
+ let cleanups = []
+
+ let cleanup = callback => cleanups.push(callback)
+
+ let [effect, cleanupEffect] = elementBoundEffect(el)
+
+ cleanups.push(cleanupEffect)
+
+ let utilities = {
+ Alpine,
+ effect,
+ cleanup,
+ evaluateLater: evaluateLater.bind(evaluateLater, el),
+ evaluate: evaluate.bind(evaluate, el),
+ }
+
+ let doCleanup = () => cleanups.forEach(i => i())
+
+ return [utilities, doCleanup]
+}
+
+export function getDirectiveHandler(el, directive) {
+ let noop = () => {}
+
+ let handler = directiveHandlers[directive.type] || noop
+
+ let [utilities, cleanup] = getElementBoundUtilities(el)
+
+ onAttributeRemoved(el, directive.original, cleanup)
+
+ let fullHandler = () => {
+ if (el._x_ignore || el._x_ignoreSelf) return
+
+ handler.inline && handler.inline(el, directive, utilities)
+
+ handler = handler.bind(handler, el, directive, utilities)
+
+ isDeferringHandlers ? directiveHandlerStacks.get(currentHandlerStackKey).push(handler) : handler()
+ }
+
+ fullHandler.runCleanups = cleanup
+
+ return fullHandler
+}
+
+export let startingWith = (subject, replacement) => ({ name, value }) => {
+ if (name.startsWith(subject)) name = name.replace(subject, replacement)
+
+ return { name, value }
+}
+
+export let into = i => i
+
+function toTransformedAttributes(callback = () => {}) {
+ return ({ name, value }) => {
+ let { name: newName, value: newValue } = attributeTransformers.reduce((carry, transform) => {
+ return transform(carry)
+ }, { name, value })
+
+ if (newName !== name) callback(newName, name)
+
+ return { name: newName, value: newValue }
+ }
+}
+
+let attributeTransformers = []
+
+export function mapAttributes(callback) {
+ attributeTransformers.push(callback)
+}
+
+function outNonAlpineAttributes({ name }) {
+ return alpineAttributeRegex().test(name)
+}
+
+let alpineAttributeRegex = () => (new RegExp(`^${prefixAsString}([^:^.]+)\\b`))
+
+function toParsedDirectives(transformedAttributeMap, originalAttributeOverride) {
+ return ({ name, value }) => {
+ let typeMatch = name.match(alpineAttributeRegex())
+ let valueMatch = name.match(/:([a-zA-Z0-9\-:]+)/)
+ let modifiers = name.match(/\.[^.\]]+(?=[^\]]*$)/g) || []
+ let original = originalAttributeOverride || transformedAttributeMap[name] || name
+
+ return {
+ type: typeMatch ? typeMatch[1] : null,
+ value: valueMatch ? valueMatch[1] : null,
+ modifiers: modifiers.map(i => i.replace('.', '')),
+ expression: value,
+ original,
+ }
+ }
+}
+
+const DEFAULT = 'DEFAULT'
+
+let directiveOrder = [
+ 'ignore',
+ 'ref',
+ 'data',
+ 'id',
+ 'bind',
+ 'init',
+ 'for',
+ 'model',
+ 'modelable',
+ 'transition',
+ 'show',
+ 'if',
+ DEFAULT,
+ 'teleport',
+ 'element',
+]
+
+function byPriority(a, b) {
+ let typeA = directiveOrder.indexOf(a.type) === -1 ? DEFAULT : a.type
+ let typeB = directiveOrder.indexOf(b.type) === -1 ? DEFAULT : b.type
+
+ return directiveOrder.indexOf(typeA) - directiveOrder.indexOf(typeB)
+}