tacel-canva 1.0.0
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/README.md +637 -0
- package/canva-api.js +271 -0
- package/canva.css +2928 -0
- package/canva.js +2910 -0
- package/index.js +20 -0
- package/package.json +38 -0
- package/themes.js +705 -0
- package/utils/dom.js +98 -0
- package/utils/pkce.js +57 -0
package/utils/dom.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOM utility functions for Canva module
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const DomUtils = {
|
|
6
|
+
/**
|
|
7
|
+
* Create an element with attributes and children
|
|
8
|
+
* @param {string} tag - Element tag name
|
|
9
|
+
* @param {Object} options - { className, text, attrs, children }
|
|
10
|
+
* @returns {HTMLElement}
|
|
11
|
+
*/
|
|
12
|
+
el(tag, options = {}) {
|
|
13
|
+
const el = document.createElement(tag);
|
|
14
|
+
|
|
15
|
+
if (options.className) {
|
|
16
|
+
el.className = options.className;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (options.text) {
|
|
20
|
+
el.textContent = options.text;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (options.html) {
|
|
24
|
+
el.innerHTML = options.html;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (options.attrs) {
|
|
28
|
+
for (const [key, value] of Object.entries(options.attrs)) {
|
|
29
|
+
el.setAttribute(key, value);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (options.children) {
|
|
34
|
+
options.children.forEach(child => {
|
|
35
|
+
if (child) el.appendChild(child);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return el;
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Clear all children from an element
|
|
44
|
+
* @param {HTMLElement} el
|
|
45
|
+
*/
|
|
46
|
+
clear(el) {
|
|
47
|
+
while (el.firstChild) {
|
|
48
|
+
el.removeChild(el.firstChild);
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Show element
|
|
54
|
+
* @param {HTMLElement} el
|
|
55
|
+
*/
|
|
56
|
+
show(el) {
|
|
57
|
+
el.style.display = '';
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Hide element
|
|
62
|
+
* @param {HTMLElement} el
|
|
63
|
+
*/
|
|
64
|
+
hide(el) {
|
|
65
|
+
el.style.display = 'none';
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Format date to readable string
|
|
70
|
+
* @param {number} timestamp - Unix timestamp in seconds
|
|
71
|
+
* @returns {string}
|
|
72
|
+
*/
|
|
73
|
+
formatDate(timestamp) {
|
|
74
|
+
const date = new Date(timestamp * 1000);
|
|
75
|
+
return date.toLocaleDateString('en-US', {
|
|
76
|
+
year: 'numeric',
|
|
77
|
+
month: 'short',
|
|
78
|
+
day: 'numeric'
|
|
79
|
+
});
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Format file size to human readable
|
|
84
|
+
* @param {number} bytes
|
|
85
|
+
* @returns {string}
|
|
86
|
+
*/
|
|
87
|
+
formatFileSize(bytes) {
|
|
88
|
+
if (bytes === 0) return '0 Bytes';
|
|
89
|
+
const k = 1024;
|
|
90
|
+
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
91
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
92
|
+
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
if (typeof module !== 'undefined' && module.exports) {
|
|
97
|
+
module.exports = DomUtils;
|
|
98
|
+
}
|
package/utils/pkce.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PKCE (Proof Key for Code Exchange) utilities for OAuth 2.0
|
|
3
|
+
* Required by Canva Connect API
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Generate a cryptographically random code verifier
|
|
8
|
+
* @returns {string} Base64-URL encoded random string (43-128 chars)
|
|
9
|
+
*/
|
|
10
|
+
function generateCodeVerifier() {
|
|
11
|
+
const array = new Uint8Array(32);
|
|
12
|
+
crypto.getRandomValues(array);
|
|
13
|
+
return base64UrlEncode(array);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Generate code challenge from verifier using SHA-256
|
|
18
|
+
* @param {string} verifier - The code verifier
|
|
19
|
+
* @returns {Promise<string>} Base64-URL encoded SHA-256 hash
|
|
20
|
+
*/
|
|
21
|
+
async function generateCodeChallenge(verifier) {
|
|
22
|
+
const encoder = new TextEncoder();
|
|
23
|
+
const data = encoder.encode(verifier);
|
|
24
|
+
const hash = await crypto.subtle.digest('SHA-256', data);
|
|
25
|
+
return base64UrlEncode(new Uint8Array(hash));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Base64-URL encode (without padding)
|
|
30
|
+
* @param {Uint8Array} buffer
|
|
31
|
+
* @returns {string}
|
|
32
|
+
*/
|
|
33
|
+
function base64UrlEncode(buffer) {
|
|
34
|
+
const base64 = btoa(String.fromCharCode(...buffer));
|
|
35
|
+
return base64
|
|
36
|
+
.replace(/\+/g, '-')
|
|
37
|
+
.replace(/\//g, '_')
|
|
38
|
+
.replace(/=/g, '');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Generate PKCE pair (verifier + challenge)
|
|
43
|
+
* @returns {Promise<{verifier: string, challenge: string}>}
|
|
44
|
+
*/
|
|
45
|
+
async function generatePKCE() {
|
|
46
|
+
const verifier = generateCodeVerifier();
|
|
47
|
+
const challenge = await generateCodeChallenge(verifier);
|
|
48
|
+
return { verifier, challenge };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (typeof module !== 'undefined' && module.exports) {
|
|
52
|
+
module.exports = {
|
|
53
|
+
generateCodeVerifier,
|
|
54
|
+
generateCodeChallenge,
|
|
55
|
+
generatePKCE,
|
|
56
|
+
};
|
|
57
|
+
}
|