]> BookStack Code Mirror - bookstack/blobdiff - resources/js/services/components.js
add tests for priority
[bookstack] / resources / js / services / components.js
index 7434f643071878466fc0fdd4e9739513d9dcf6c8..beb0ce92fbf38863e91f27e03e8528f7e86cc378 100644 (file)
@@ -1,3 +1,5 @@
+import {kebabToCamel, camelToKebab} from './text';
+
 /**
  * A mapping of active components keyed by name, with values being arrays of component
  * instances since there can be multiple components of the same type.
@@ -17,44 +19,6 @@ const componentModelMap = {};
  */
 const elementComponentMap = new WeakMap();
 
-/**
- * Initialize a component instance on the given dom element.
- * @param {String} name
- * @param {Element} element
- */
-function initComponent(name, element) {
-    /** @type {Function<Component>|undefined} **/
-    const componentModel = componentModelMap[name];
-    if (componentModel === undefined) return;
-
-    // Create our component instance
-    /** @type {Component} **/
-    let instance;
-    try {
-        instance = new componentModel();
-        instance.$name = name;
-        instance.$el = element;
-        const allRefs = parseRefs(name, element);
-        instance.$refs = allRefs.refs;
-        instance.$manyRefs = allRefs.manyRefs;
-        instance.$opts = parseOpts(name, element);
-        instance.setup();
-    } catch (e) {
-        console.error('Failed to create component', e, name, element);
-    }
-
-    // Add to global listing
-    if (typeof components[name] === "undefined") {
-        components[name] = [];
-    }
-    components[name].push(instance);
-
-    // Add to element mapping
-    const elComponents = elementComponentMap.get(element) || {};
-    elComponents[name] = instance;
-    elementComponentMap.set(element, elComponents);
-}
-
 /**
  * Parse out the element references within the given element
  * for the given component name.
@@ -65,7 +29,7 @@ function parseRefs(name, element) {
     const refs = {};
     const manyRefs = {};
 
-    const prefix = `${name}@`
+    const prefix = `${name}@`;
     const selector = `[refs*="${prefix}"]`;
     const refElems = [...element.querySelectorAll(selector)];
     if (element.matches(selector)) {
@@ -91,13 +55,13 @@ function parseRefs(name, element) {
 
 /**
  * Parse out the element component options.
- * @param {String} name
+ * @param {String} componentName
  * @param {Element} element
  * @return {Object<String, String>}
  */
-function parseOpts(name, element) {
+function parseOpts(componentName, element) {
     const opts = {};
-    const prefix = `option:${name}:`;
+    const prefix = `option:${componentName}:`;
     for (const {name, value} of element.attributes) {
         if (name.startsWith(prefix)) {
             const optName = name.replace(prefix, '');
@@ -108,14 +72,41 @@ function parseOpts(name, element) {
 }
 
 /**
- * Convert a kebab-case string to camelCase
- * @param {String} kebab
- * @returns {string}
+ * Initialize a component instance on the given dom element.
+ * @param {String} name
+ * @param {Element} element
  */
-function kebabToCamel(kebab) {
-    const ucFirst = (word) => word.slice(0,1).toUpperCase() + word.slice(1);
-    const words = kebab.split('-');
-    return words[0] + words.slice(1).map(ucFirst).join('');
+function initComponent(name, element) {
+    /** @type {Function<Component>|undefined} * */
+    const ComponentModel = componentModelMap[name];
+    if (ComponentModel === undefined) return;
+
+    // Create our component instance
+    /** @type {Component} * */
+    let instance;
+    try {
+        instance = new ComponentModel();
+        instance.$name = name;
+        instance.$el = element;
+        const allRefs = parseRefs(name, element);
+        instance.$refs = allRefs.refs;
+        instance.$manyRefs = allRefs.manyRefs;
+        instance.$opts = parseOpts(name, element);
+        instance.setup();
+    } catch (e) {
+        console.error('Failed to create component', e, name, element);
+    }
+
+    // Add to global listing
+    if (typeof components[name] === 'undefined') {
+        components[name] = [];
+    }
+    components[name].push(instance);
+
+    // Add to element mapping
+    const elComponents = elementComponentMap.get(element) || {};
+    elComponents[name] = instance;
+    elementComponentMap.set(element, elComponents);
 }
 
 /**
@@ -123,7 +114,7 @@ function kebabToCamel(kebab) {
  * @param {Element|Document} parentElement
  */
 export function init(parentElement = document) {
-    const componentElems = parentElement.querySelectorAll(`[component],[components]`);
+    const componentElems = parentElement.querySelectorAll('[component],[components]');
 
     for (const el of componentElems) {
         const componentNames = `${el.getAttribute('component') || ''} ${(el.getAttribute('components'))}`.toLowerCase().split(' ').filter(Boolean);
@@ -172,7 +163,3 @@ export function firstOnElement(element, name) {
     const elComponents = elementComponentMap.get(element) || {};
     return elComponents[name] || null;
 }
-
-function camelToKebab(camelStr) {
-    return camelStr.replace(/[A-Z]/g, (str, offset) =>  (offset > 0 ? '-' : '') + str.toLowerCase());
-}
\ No newline at end of file