@cocreate/utils 1.39.2 → 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.
Files changed (3) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/package.json +1 -1
  3. package/src/index.js +122 -85
package/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
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
+
8
+ # [1.40.0](https://github.com/CoCreate-app/CoCreate-utils/compare/v1.39.2...v1.40.0) (2025-10-08)
9
+
10
+
11
+ ### Features
12
+
13
+ * add getRelativePath function to compute relative paths based on current location ([786ed1b](https://github.com/CoCreate-app/CoCreate-utils/commit/786ed1b642febad9c5fda1c9f5534e829f5fd6c6))
14
+ * enhance getRelativePath function to handle default path and localhost scenarios ([cd0b369](https://github.com/CoCreate-app/CoCreate-utils/commit/cd0b3692b1753d06805670c59d832a00e7b85a64))
15
+
1
16
  ## [1.39.2](https://github.com/CoCreate-app/CoCreate-utils/compare/v1.39.1...v1.39.2) (2025-09-01)
2
17
 
3
18
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/utils",
3
- "version": "1.39.2",
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
@@ -40,6 +40,33 @@
40
40
  }
41
41
  }
42
42
 
43
+ function getRelativePath(path) {
44
+ // If no path provided, use window.location.pathname
45
+ if (!path && isBrowser) {
46
+ path = window.location.pathname.replace(/\/[^\/]*$/, ""); // Remove file from path
47
+ }
48
+
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
51
+ if (
52
+ isBrowser &&
53
+ (location.hostname === "localhost" ||
54
+ location.hostname === "127.0.0.1")
55
+ ) {
56
+ // Find the '/src' directory in the path and keep everything after it (exclude '/src' itself)
57
+ const srcIndex = path.indexOf("/src");
58
+ if (srcIndex !== -1) {
59
+ path = path.slice(srcIndex + 4); // remove '/src' and everything before it
60
+ }
61
+ }
62
+
63
+ if (!path.endsWith("/")) {
64
+ path += "/";
65
+ }
66
+ let depth = path.split("/").filter(Boolean).length;
67
+ return depth > 0 ? "../".repeat(depth) : "./";
68
+ }
69
+
43
70
  /**
44
71
  * Generates an ObjectId
45
72
  */
@@ -289,13 +316,14 @@
289
316
 
290
317
  function getValueFromObject(object = {}, path = "", throwError = false) {
291
318
  try {
292
- if (!Object.keys(object).length || !path) {
319
+ if ((!Array.isArray(object) && !Object.keys(object).length) || !path) {
293
320
  if (throwError)
294
321
  throw new Error("Invalid input to getValueFromObject");
295
322
  return;
296
323
  }
297
324
 
298
- path = path.replace(/\[(\d+)\]/g, ".$1");
325
+ // remove leading dot if path is like `[0].src`
326
+ path = path.replace(/\[(\d+)\]/g, ".$1").replace(/^\./, '');
299
327
 
300
328
  let data = object,
301
329
  subpath = path.split(".");
@@ -681,106 +709,114 @@
681
709
  * @returns {Array} - An array of elements that match the query.
682
710
  */
683
711
  function queryElements({ element = document, prefix, selector }) {
684
- // Initialize a Set to store unique elements.
685
- let elements = new Set();
686
-
687
- // If no selector is provided and the element is an element node.
688
- if (!selector && element.nodeType === 1) {
689
- // If no prefix is provided, derive one from the element's attributes.
690
- if (!prefix) {
691
- for (let attr of element.attributes) {
692
- // If an attribute with "-query" suffix is found, extract prefix.
693
- if (attr.name.endsWith("-query")) {
694
- 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
+ }
695
725
  }
726
+ // If no valid prefix is found, exit the function.
727
+ if (!prefix) return [];
696
728
  }
697
- // If no valid prefix is found, exit the function.
698
- 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.
699
732
  }
700
- // Get the selector using the derived prefix.
701
- selector = element.getAttribute(prefix + "-" + "query");
702
- if (!selector) return false; // Exit if no selector is found.
703
- }
704
733
 
705
- // Split complex selectors into individual ones, handling nested structures.
706
- let selectors = selector.split(/,(?![^()\[\]]*[)\]])/g);
707
- for (let i = 0; i < selectors.length; i++) {
708
- 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.
709
738
 
710
- let queriedElement = element; // Start query from the current element.
739
+ let queriedElement = element; // Start query from the current element.
711
740
 
712
- // If media queries are included, verify and filter the selector accordingly.
713
- if (selectors[i].includes("@")) {
714
- selectors[i] = checkMediaQueries(selectors[i]);
715
- if (selectors[i] === false) continue; // Skip if media query is not matched.
716
- }
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
+ }
717
782
 
718
- let remainingSelector = selectors[i].trim(); // Trim any whitespace.
719
- let match;
720
-
721
- // Process each part of the selector that corresponds to specific query types/operators.
722
- while ((match = queryTypesRegex.exec(remainingSelector)) !== null) {
723
- const matchIndex = match.index;
724
- const operator = match[0];
725
-
726
- // Process the part before the operator (if any).
727
- const part = remainingSelector
728
- .substring(0, matchIndex)
729
- .trim()
730
- .replace(/,$/, "");
731
- if (part) {
732
- queriedElement = querySelector(queriedElement, part);
733
783
  if (!queriedElement) break; // Exit loop if no element is found.
734
784
  }
735
785
 
736
- // Remove the processed part and operator from the remaining selector.
737
- remainingSelector = remainingSelector
738
- .substring(matchIndex + operator.length)
739
- .trim();
786
+ if (!queriedElement) continue; // Skip if no element is found.
740
787
 
741
- // Handle the $closest operator specifically.
742
- if (operator === "$closest") {
743
- let [closest, remaining = ""] = remainingSelector.split(
744
- /\s+/,
745
- 2
788
+ // Process the remaining part after the last operator (if any).
789
+ if (remainingSelector) {
790
+ queriedElement = querySelector(
791
+ queriedElement,
792
+ remainingSelector
746
793
  );
747
- queriedElement = queriedElement.closest(closest);
748
- remainingSelector = remaining.trim();
749
- } else {
750
- // Process other operators using the queryType function.
751
- queriedElement = queryType(queriedElement, operator);
752
794
  }
753
795
 
754
- if (!queriedElement) break; // Exit loop if no element is found.
755
- }
756
-
757
- if (!queriedElement) continue; // Skip if no element is found.
758
-
759
- // Process the remaining part after the last operator (if any).
760
- if (remainingSelector) {
761
- queriedElement = querySelector(
762
- queriedElement,
763
- remainingSelector
764
- );
765
- }
766
-
767
- // Add elements to the set.
768
- if (
769
- Array.isArray(queriedElement) ||
770
- queriedElement instanceof HTMLCollection ||
771
- queriedElement instanceof NodeList
772
- ) {
773
- for (let el of queriedElement) {
774
- if (el instanceof Element) {
775
- 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
+ }
776
806
  }
807
+ } else if (queriedElement instanceof Element) {
808
+ elements.add(queriedElement);
777
809
  }
778
- } else if (queriedElement instanceof Element) {
779
- elements.add(queriedElement);
780
810
  }
781
- }
782
811
 
783
- 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
+ }
784
820
  }
785
821
 
786
822
  function queryType(element, type) {
@@ -1248,6 +1284,7 @@
1248
1284
  if (isBrowser) clickedElement();
1249
1285
 
1250
1286
  return {
1287
+ getRelativePath,
1251
1288
  ObjectId,
1252
1289
  checkValue,
1253
1290
  isValidDate,
@@ -1269,4 +1306,4 @@
1269
1306
  setAttributeNames,
1270
1307
  getAttributeNames
1271
1308
  };
1272
- });
1309
+ });