@cocreate/utils 1.40.0 → 1.40.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## [1.40.1](https://github.com/CoCreate-app/CoCreate-utils/compare/v1.40.0...v1.40.1) (2025-10-10)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * refine getRelativePath handling for localhost and improve getValueFromObject validation ([b7bd32f](https://github.com/CoCreate-app/CoCreate-utils/commit/b7bd32fa83d503108e9398e40c1c519caadb8ed5))
7
+
1
8
  # [1.40.0](https://github.com/CoCreate-app/CoCreate-utils/compare/v1.39.2...v1.40.0) (2025-10-08)
2
9
 
3
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/utils",
3
- "version": "1.40.0",
3
+ "version": "1.40.1",
4
4
  "description": "A simple utils component in vanilla javascript. Easily configured using HTML5 attributes and/or JavaScript API.",
5
5
  "keywords": [
6
6
  "utils",
package/src/index.js CHANGED
@@ -46,15 +46,17 @@
46
46
  path = window.location.pathname.replace(/\/[^\/]*$/, ""); // Remove file from path
47
47
  }
48
48
 
49
- // For localhost/127.0.0.1, trim everything after '/src'
49
+ // For localhost/127.0.0.1, remove everything up to and including the first '/src'
50
+ // so content AFTER '/src' is treated as the root
50
51
  if (
51
52
  isBrowser &&
52
53
  (location.hostname === "localhost" ||
53
54
  location.hostname === "127.0.0.1")
54
55
  ) {
56
+ // Find the '/src' directory in the path and keep everything after it (exclude '/src' itself)
55
57
  const srcIndex = path.indexOf("/src");
56
58
  if (srcIndex !== -1) {
57
- path = path.substring(0, srcIndex + 4); // keep '/src'
59
+ path = path.slice(srcIndex + 4); // remove '/src' and everything before it
58
60
  }
59
61
  }
60
62
 
@@ -314,13 +316,14 @@
314
316
 
315
317
  function getValueFromObject(object = {}, path = "", throwError = false) {
316
318
  try {
317
- if (!Object.keys(object).length || !path) {
319
+ if ((!Array.isArray(object) && !Object.keys(object).length) || !path) {
318
320
  if (throwError)
319
321
  throw new Error("Invalid input to getValueFromObject");
320
322
  return;
321
323
  }
322
324
 
323
- path = path.replace(/\[(\d+)\]/g, ".$1");
325
+ // remove leading dot if path is like `[0].src`
326
+ path = path.replace(/\[(\d+)\]/g, ".$1").replace(/^\./, '');
324
327
 
325
328
  let data = object,
326
329
  subpath = path.split(".");
@@ -706,106 +709,114 @@
706
709
  * @returns {Array} - An array of elements that match the query.
707
710
  */
708
711
  function queryElements({ element = document, prefix, selector }) {
709
- // Initialize a Set to store unique elements.
710
- let elements = new Set();
711
-
712
- // If no selector is provided and the element is an element node.
713
- if (!selector && element.nodeType === 1) {
714
- // If no prefix is provided, derive one from the element's attributes.
715
- if (!prefix) {
716
- for (let attr of element.attributes) {
717
- // If an attribute with "-query" suffix is found, extract prefix.
718
- if (attr.name.endsWith("-query")) {
719
- prefix = attr.name.slice(0, -6);
712
+ try {
713
+ // Initialize a Set to store unique elements.
714
+ let elements = new Set();
715
+
716
+ // If no selector is provided and the element is an element node.
717
+ if (!selector && element.nodeType === 1) {
718
+ // If no prefix is provided, derive one from the element's attributes.
719
+ if (!prefix) {
720
+ for (let attr of element.attributes) {
721
+ // If an attribute with "-query" suffix is found, extract prefix.
722
+ if (attr.name.endsWith("-query")) {
723
+ prefix = attr.name.slice(0, -6);
724
+ }
720
725
  }
726
+ // If no valid prefix is found, exit the function.
727
+ if (!prefix) return [];
721
728
  }
722
- // If no valid prefix is found, exit the function.
723
- if (!prefix) return false;
729
+ // Get the selector using the derived prefix.
730
+ selector = element.getAttribute(prefix + "-" + "query");
731
+ if (!selector) return []; // Exit if no selector is found.
724
732
  }
725
- // Get the selector using the derived prefix.
726
- selector = element.getAttribute(prefix + "-" + "query");
727
- if (!selector) return false; // Exit if no selector is found.
728
- }
729
733
 
730
- // Split complex selectors into individual ones, handling nested structures.
731
- let selectors = selector.split(/,(?![^()\[\]]*[)\]])/g);
732
- for (let i = 0; i < selectors.length; i++) {
733
- if (!selectors[i]) continue; // Skip empty selectors.
734
+ // Split complex selectors into individual ones, handling nested structures.
735
+ let selectors = selector.split(/,(?![^()\[\]]*[)\]])/g);
736
+ for (let i = 0; i < selectors.length; i++) {
737
+ if (!selectors[i]) continue; // Skip empty selectors.
734
738
 
735
- let queriedElement = element; // Start query from the current element.
739
+ let queriedElement = element; // Start query from the current element.
736
740
 
737
- // If media queries are included, verify and filter the selector accordingly.
738
- if (selectors[i].includes("@")) {
739
- selectors[i] = checkMediaQueries(selectors[i]);
740
- if (selectors[i] === false) continue; // Skip if media query is not matched.
741
- }
741
+ // If media queries are included, verify and filter the selector accordingly.
742
+ if (selectors[i].includes("@")) {
743
+ selectors[i] = checkMediaQueries(selectors[i]);
744
+ if (selectors[i] === false) continue; // Skip if media query is not matched.
745
+ }
746
+
747
+ let remainingSelector = selectors[i].trim(); // Trim any whitespace.
748
+ let match;
749
+
750
+ // Process each part of the selector that corresponds to specific query types/operators.
751
+ while (
752
+ (match = queryTypesRegex.exec(remainingSelector)) !== null
753
+ ) {
754
+ const matchIndex = match.index;
755
+ const operator = match[0];
756
+
757
+ // Process the part before the operator (if any).
758
+ const part = remainingSelector
759
+ .substring(0, matchIndex)
760
+ .trim()
761
+ .replace(/,$/, "");
762
+ if (part) {
763
+ queriedElement = querySelector(queriedElement, part);
764
+ if (!queriedElement) break; // Exit loop if no element is found.
765
+ }
766
+
767
+ // Remove the processed part and operator from the remaining selector.
768
+ remainingSelector = remainingSelector
769
+ .substring(matchIndex + operator.length)
770
+ .trim();
771
+
772
+ // Handle the $closest operator specifically.
773
+ if (operator === "$closest") {
774
+ let [closest, remaining = ""] =
775
+ remainingSelector.split(/\s+/, 2);
776
+ queriedElement = queriedElement.closest(closest);
777
+ remainingSelector = remaining.trim();
778
+ } else {
779
+ // Process other operators using the queryType function.
780
+ queriedElement = queryType(queriedElement, operator);
781
+ }
742
782
 
743
- let remainingSelector = selectors[i].trim(); // Trim any whitespace.
744
- let match;
745
-
746
- // Process each part of the selector that corresponds to specific query types/operators.
747
- while ((match = queryTypesRegex.exec(remainingSelector)) !== null) {
748
- const matchIndex = match.index;
749
- const operator = match[0];
750
-
751
- // Process the part before the operator (if any).
752
- const part = remainingSelector
753
- .substring(0, matchIndex)
754
- .trim()
755
- .replace(/,$/, "");
756
- if (part) {
757
- queriedElement = querySelector(queriedElement, part);
758
783
  if (!queriedElement) break; // Exit loop if no element is found.
759
784
  }
760
785
 
761
- // Remove the processed part and operator from the remaining selector.
762
- remainingSelector = remainingSelector
763
- .substring(matchIndex + operator.length)
764
- .trim();
786
+ if (!queriedElement) continue; // Skip if no element is found.
765
787
 
766
- // Handle the $closest operator specifically.
767
- if (operator === "$closest") {
768
- let [closest, remaining = ""] = remainingSelector.split(
769
- /\s+/,
770
- 2
788
+ // Process the remaining part after the last operator (if any).
789
+ if (remainingSelector) {
790
+ queriedElement = querySelector(
791
+ queriedElement,
792
+ remainingSelector
771
793
  );
772
- queriedElement = queriedElement.closest(closest);
773
- remainingSelector = remaining.trim();
774
- } else {
775
- // Process other operators using the queryType function.
776
- queriedElement = queryType(queriedElement, operator);
777
794
  }
778
795
 
779
- if (!queriedElement) break; // Exit loop if no element is found.
780
- }
781
-
782
- if (!queriedElement) continue; // Skip if no element is found.
783
-
784
- // Process the remaining part after the last operator (if any).
785
- if (remainingSelector) {
786
- queriedElement = querySelector(
787
- queriedElement,
788
- remainingSelector
789
- );
790
- }
791
-
792
- // Add elements to the set.
793
- if (
794
- Array.isArray(queriedElement) ||
795
- queriedElement instanceof HTMLCollection ||
796
- queriedElement instanceof NodeList
797
- ) {
798
- for (let el of queriedElement) {
799
- if (el instanceof Element) {
800
- elements.add(el);
796
+ // Add elements to the set.
797
+ if (
798
+ Array.isArray(queriedElement) ||
799
+ queriedElement instanceof HTMLCollection ||
800
+ queriedElement instanceof NodeList
801
+ ) {
802
+ for (let el of queriedElement) {
803
+ if (el instanceof Element) {
804
+ elements.add(el);
805
+ }
801
806
  }
807
+ } else if (queriedElement instanceof Element) {
808
+ elements.add(queriedElement);
802
809
  }
803
- } else if (queriedElement instanceof Element) {
804
- elements.add(queriedElement);
805
810
  }
806
- }
807
811
 
808
- return Array.from(elements); // Convert Set to Array and return found elements.
812
+ return Array.from(elements); // Convert Set to Array and return found elements.
813
+ } catch (e) {
814
+ console.error(
815
+ `CoCreate: Error in queryElements with selector: "${selector}".`,
816
+ e
817
+ );
818
+ return [];
819
+ }
809
820
  }
810
821
 
811
822
  function queryType(element, type) {