@muscara/htmx-jsonata 0.0.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/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ GLWT (Good Luck With That) Public License
2
+ Copyright (c) Everyone, except Author
3
+
4
+ Everyone is permitted to copy, distribute, modify, merge, sell, publish,
5
+ sublicense or whatever they want with this software but at their own risk.
6
+
7
+ Preamble
8
+
9
+ The author has absolutely no responsibility for what mess this project may cause.
10
+ It might just work, it might not, there is no third option.
11
+
12
+ Terms and Conditions for Copying, Distribution, and Modification
13
+
14
+ You may do whatever you want to as long as you never leave a
15
+ trace to track the author of the original product to blame for or hold
16
+ responsible.
17
+
18
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,22 @@
1
+ # htmx-jsonata
2
+
3
+ [htmx extension](https://htmx.org/extensions) that provides [jsonata](https://jsonata.org) query functionality for htmx elements
4
+
5
+ > only GET request method is supported
6
+
7
+ ## usage
8
+
9
+ ```html
10
+ <div jsonata-url="https://jsonplaceholder.typicode.com/users" jsonata="$[name='Leanne Graham']">
11
+ <h1 jsonata-property="name"></h1>
12
+ <p jsonata-property="phone"></p>
13
+ </div>
14
+ ```
15
+
16
+ ### attributes
17
+
18
+ `jsonata-url` (required): the JSON API URL to fetch data from.
19
+
20
+ `jsonata`: jsonata expression to filter, transform, or query the JSON response.
21
+
22
+ `jsonata-property`: specifies which property from the parsed result to display in the element.
@@ -0,0 +1,130 @@
1
+ (function() {
2
+ const jsonataLib = window.jsonata || (typeof jsonata !== 'undefined' ? jsonata : null);
3
+
4
+ if (!jsonataLib) {
5
+ console.error('htmx-jsonata extension requires the jsonata library. Include it before this extension.');
6
+ return;
7
+ }
8
+
9
+ if (typeof htmx !== 'undefined') {
10
+ htmx.defineExtension('jsonata', {
11
+ onEvent: function(name, evt) {
12
+ if (name === 'htmx:afterProcessNode') {
13
+ const elt = evt.detail.elt;
14
+ const jsonataUrl = elt.getAttribute('jsonata-url');
15
+
16
+ if (jsonataUrl) processJsonataElement(elt, jsonataUrl)
17
+ }
18
+ return true;
19
+ }
20
+ });
21
+ }
22
+
23
+ function processJsonataElement(element, url) {
24
+ const jsonataExpression = element.getAttribute('jsonata');
25
+
26
+ fetch(url)
27
+ .then(response => {
28
+ if (!response.ok) {
29
+ throw new Error(`error: ${response.status}`);
30
+ }
31
+
32
+ return response.json();
33
+ })
34
+ .then(data => {
35
+ let result = data;
36
+ if (jsonataExpression) {
37
+ try {
38
+ const expression = jsonataLib(jsonataExpression);
39
+ const evaluateResult = expression.evaluate(data);
40
+
41
+ Promise.resolve(evaluateResult).then(evalResult => {
42
+ result = evalResult;
43
+
44
+ if (Array.isArray(result) && result.length === 1) {
45
+ result = result[0];
46
+ }
47
+
48
+ populateElements(element, result);
49
+ });
50
+ } catch (error) {
51
+ console.error('Error evaluating jsonata expression:', error);
52
+ return;
53
+ }
54
+ } else {
55
+ populateElements(element, result);
56
+ }
57
+ })
58
+ .catch(error => {
59
+ console.error('Error fetching or processing jsonata data:', error);
60
+ });
61
+ }
62
+
63
+ function populateElements(element, result) {
64
+ const propertyElements = element.querySelectorAll('[jsonata-property]');
65
+
66
+ propertyElements.forEach(propElt => {
67
+ const propertyName = propElt.getAttribute('jsonata-property');
68
+
69
+ if (result && propertyName) {
70
+ const value = getNestedProperty(result, propertyName);
71
+
72
+ if (value !== undefined && value !== null) {
73
+ if (propElt.tagName === 'INPUT' || propElt.tagName === 'TEXTAREA') {
74
+ propElt.value = value;
75
+ } else {
76
+ propElt.textContent = value;
77
+ }
78
+ }
79
+ }
80
+ });
81
+ }
82
+
83
+ function getNestedProperty(obj, path) {
84
+ if (!obj || !path) return undefined;
85
+ let result = obj;
86
+ const parts = path.split('.');
87
+
88
+ for (const part of parts) {
89
+ const arrayMatch = part.match(/^(.+?)\[(\d+)\]$/);
90
+
91
+ if (arrayMatch) {
92
+ const propName = arrayMatch[1];
93
+ const index = parseInt(arrayMatch[2], 10);
94
+
95
+ if (result && typeof result === 'object' && propName in result) {
96
+ result = result[propName];
97
+ if (Array.isArray(result) && index >= 0 && index < result.length) {
98
+ result = result[index];
99
+ } else {
100
+ return undefined;
101
+ }
102
+ } else {
103
+ return undefined;
104
+ }
105
+ } else {
106
+ if (result && typeof result === 'object' && part in result) {
107
+ result = result[part];
108
+ } else {
109
+ return undefined;
110
+ }
111
+ }
112
+ }
113
+
114
+ return result;
115
+ }
116
+
117
+ function initializeJsonataElements() {
118
+ const elements = document.querySelectorAll('[jsonata-url]');
119
+ elements.forEach(elt => {
120
+ const url = elt.getAttribute('jsonata-url');
121
+ if (url) processJsonataElement(elt, url);
122
+ });
123
+ }
124
+
125
+ if (document.readyState === 'loading') {
126
+ document.addEventListener('DOMContentLoaded', () => initializeJsonataElements());
127
+ } else {
128
+ initializeJsonataElements();
129
+ }
130
+ })();
@@ -0,0 +1 @@
1
+ !function(){const t=window.jsonata||("undefined"!=typeof jsonata?jsonata:null);function e(e,o){const r=e.getAttribute("jsonata");fetch(o).then((t=>{if(!t.ok)throw new Error(`error: ${t.status}`);return t.json()})).then((o=>{let a=o;if(r)try{const s=t(r).evaluate(o);Promise.resolve(s).then((t=>{a=t,Array.isArray(a)&&1===a.length&&(a=a[0]),n(e,a)}))}catch(t){return void console.error("Error evaluating jsonata expression:",t)}else n(e,a)})).catch((t=>{console.error("Error fetching or processing jsonata data:",t)}))}function n(t,e){t.querySelectorAll("[jsonata-property]").forEach((t=>{const n=t.getAttribute("jsonata-property");if(e&&n){const o=function(t,e){if(!t||!e)return;let n=t;const o=e.split(".");for(const t of o){const e=t.match(/^(.+?)\[(\d+)\]$/);if(e){const t=e[1],o=parseInt(e[2],10);if(!n||"object"!=typeof n||!(t in n))return;if(n=n[t],!(Array.isArray(n)&&o>=0&&o<n.length))return;n=n[o]}else{if(!n||"object"!=typeof n||!(t in n))return;n=n[t]}}return n}(e,n);null!=o&&("INPUT"===t.tagName||"TEXTAREA"===t.tagName?t.value=o:t.textContent=o)}}))}function o(){document.querySelectorAll("[jsonata-url]").forEach((t=>{const n=t.getAttribute("jsonata-url");n&&e(t,n)}))}t?("undefined"!=typeof htmx&&htmx.defineExtension("jsonata",{onEvent:function(t,n){if("htmx:afterProcessNode"===t){const t=n.detail.elt,o=t.getAttribute("jsonata-url");o&&e(t,o)}return!0}}),"loading"===document.readyState?document.addEventListener("DOMContentLoaded",(()=>o())):o()):console.error("htmx-jsonata extension requires the jsonata library. Include it before this extension.")}();
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@muscara/htmx-jsonata",
3
+ "version": "0.0.1",
4
+ "description": "htmx extension that provides jsonata query functionality for htmx elements",
5
+ "main": "htmx-jsonata.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/kevinmuscara/htmx-jsonata.git"
12
+ },
13
+ "keywords": [
14
+ "htmx",
15
+ "jsonata",
16
+ "htmx-jsonata",
17
+ "jsonata-htmx",
18
+ "htmx-json",
19
+ "json"
20
+ ],
21
+ "author": "Kevin Muscara",
22
+ "license": "SEE LICENSE IN LICENSE.md",
23
+ "bugs": {
24
+ "url": "https://github.com/kevinmuscara/htmx-jsonata/issues"
25
+ },
26
+ "homepage": "https://github.com/kevinmuscara/htmx-jsonata#readme"
27
+ }