aztomiq 1.0.2 → 1.0.4
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/package.json +4 -1
- package/scripts/builds/assets.js +30 -22
- package/scripts/builds/data.js +30 -19
- package/server.js +125 -0
- package/src/assets/css/categories.css +90 -0
- package/src/assets/css/global.css +1815 -0
- package/src/assets/css/home.css +509 -0
- package/src/assets/css/master-layout.css +133 -0
- package/src/assets/css/sidebar-layout.css +264 -0
- package/src/assets/images/logo.svg +29 -0
- package/src/assets/js/global.js +373 -0
- package/src/assets/js/home.js +138 -0
- package/src/assets/js/user-mode.js +54 -0
- package/src/assets/vendor/qrcode/qrcode.min.js +1 -0
- package/src/locales/en/common.yaml +93 -0
- package/src/locales/vi/common.yaml +93 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
document.addEventListener("DOMContentLoaded", () => {
|
|
2
|
+
// Main Homepage Logic (View Toggle & Sorting)
|
|
3
|
+
const toolGrids = document.querySelectorAll(".tools-grid");
|
|
4
|
+
const viewToggleBtns = document.querySelectorAll("[data-view]");
|
|
5
|
+
const sortSelect = document.getElementById("sort-select");
|
|
6
|
+
|
|
7
|
+
// Only proceed if we are on the homepage (elements exist)
|
|
8
|
+
if (toolGrids.length === 0) return;
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
// --- 3. View Toggle Logic ---
|
|
12
|
+
const savedView = localStorage.getItem("aztomiq_view_mode") || "grid";
|
|
13
|
+
const savedSort = localStorage.getItem("aztomiq_sort_mode") || "default";
|
|
14
|
+
|
|
15
|
+
applyView(savedView);
|
|
16
|
+
if (sortSelect) {
|
|
17
|
+
sortSelect.value = savedSort;
|
|
18
|
+
applySort(savedSort);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
viewToggleBtns.forEach((btn) => {
|
|
22
|
+
btn.addEventListener("click", () => {
|
|
23
|
+
const view = btn.dataset.view;
|
|
24
|
+
applyView(view);
|
|
25
|
+
localStorage.setItem("aztomiq_view_mode", view);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
function applyView(viewMode) {
|
|
30
|
+
toolGrids.forEach((grid) => {
|
|
31
|
+
if (viewMode === "list") grid.classList.add("list-view");
|
|
32
|
+
else grid.classList.remove("list-view");
|
|
33
|
+
});
|
|
34
|
+
viewToggleBtns.forEach((btn) => {
|
|
35
|
+
if (btn.dataset.view === viewMode) {
|
|
36
|
+
btn.classList.add("active");
|
|
37
|
+
btn.style.backgroundColor = "var(--primary-color)";
|
|
38
|
+
btn.style.color = "white";
|
|
39
|
+
} else {
|
|
40
|
+
btn.classList.remove("active");
|
|
41
|
+
btn.style.backgroundColor = "transparent";
|
|
42
|
+
btn.style.color = "var(--text-color)";
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// --- 4. Sort Logic ---
|
|
48
|
+
if (sortSelect) {
|
|
49
|
+
sortSelect.addEventListener("change", (e) => {
|
|
50
|
+
const sortMode = e.target.value;
|
|
51
|
+
applySort(sortMode);
|
|
52
|
+
localStorage.setItem("aztomiq_sort_mode", sortMode);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function applySort(sortMode) {
|
|
57
|
+
const recent = JSON.parse(localStorage.getItem('aztomiq_recent') || '{}');
|
|
58
|
+
const usage = JSON.parse(localStorage.getItem('aztomiq_usage') || '{}');
|
|
59
|
+
// Mock global popularity if provided in DOM later, for now defaults to 0
|
|
60
|
+
// We can assume static popularity is not yet available in DOM dataset.
|
|
61
|
+
|
|
62
|
+
toolGrids.forEach((grid) => {
|
|
63
|
+
const items = Array.from(grid.children);
|
|
64
|
+
|
|
65
|
+
// Save original index
|
|
66
|
+
if (!grid.dataset.indexed) {
|
|
67
|
+
items.forEach((item, index) => item.dataset.originalIndex = index);
|
|
68
|
+
grid.dataset.indexed = "true";
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
items.sort((a, b) => {
|
|
72
|
+
// Extract ID for usage lookup
|
|
73
|
+
// Href is safe bet if we can parse it, or we rely on text content for AZ
|
|
74
|
+
// Better: let's try to infer ID from href
|
|
75
|
+
const getID = (el) => {
|
|
76
|
+
const href = el.getAttribute('href');
|
|
77
|
+
if (!href) return '';
|
|
78
|
+
const parts = href.split('/').filter(Boolean);
|
|
79
|
+
return parts[parts.length - 1];
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const idA = getID(a);
|
|
83
|
+
const idB = getID(b);
|
|
84
|
+
|
|
85
|
+
if (sortMode === "az") {
|
|
86
|
+
const titleA = a.querySelector("h3")?.innerText.trim() || "";
|
|
87
|
+
const titleB = b.querySelector("h3")?.innerText.trim() || "";
|
|
88
|
+
return titleA.localeCompare(titleB);
|
|
89
|
+
} else if (sortMode === "za") {
|
|
90
|
+
const titleA = a.querySelector("h3")?.innerText.trim() || "";
|
|
91
|
+
const titleB = b.querySelector("h3")?.innerText.trim() || "";
|
|
92
|
+
return titleB.localeCompare(titleA);
|
|
93
|
+
} else if (sortMode === "recent") {
|
|
94
|
+
// Descending timestamp
|
|
95
|
+
const timeA = recent[idA] || 0;
|
|
96
|
+
const timeB = recent[idB] || 0;
|
|
97
|
+
return timeB - timeA;
|
|
98
|
+
} else if (sortMode === "popular") {
|
|
99
|
+
// Descending count
|
|
100
|
+
const countA = usage[idA] || 0;
|
|
101
|
+
const countB = usage[idB] || 0;
|
|
102
|
+
return countB - countA;
|
|
103
|
+
} else {
|
|
104
|
+
// Default
|
|
105
|
+
return parseInt(a.dataset.originalIndex) - parseInt(b.dataset.originalIndex);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
items.forEach((item) => grid.appendChild(item));
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// --- 5. Hero Search Logic (Bridge to Global Search) ---
|
|
113
|
+
const homeSearch = document.getElementById("home-search");
|
|
114
|
+
if (homeSearch) {
|
|
115
|
+
homeSearch.addEventListener("focus", () => {
|
|
116
|
+
homeSearch.blur();
|
|
117
|
+
document.getElementById("header-search-box")?.click() ||
|
|
118
|
+
document.getElementById("search-btn")?.click() ||
|
|
119
|
+
document.getElementById("search-btn-mobile")?.click();
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// --- 6. Category Filter Logic ---
|
|
124
|
+
const catFilter = document.getElementById("category-filter");
|
|
125
|
+
if (catFilter) {
|
|
126
|
+
catFilter.addEventListener("change", (e) => {
|
|
127
|
+
const cat = e.target.value;
|
|
128
|
+
const sections = document.querySelectorAll(".category-section");
|
|
129
|
+
sections.forEach(sec => {
|
|
130
|
+
if (cat === "all" || sec.id === cat + "-tools") {
|
|
131
|
+
sec.style.display = "block";
|
|
132
|
+
} else {
|
|
133
|
+
sec.style.display = "none";
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
(function () {
|
|
2
|
+
const MODE_KEY = 'aztomiq_user_mode';
|
|
3
|
+
const modes = { STANDARD: 'standard', ADVANCED: 'advanced' };
|
|
4
|
+
|
|
5
|
+
// Get saved mode or default to standard
|
|
6
|
+
let currentMode = localStorage.getItem(MODE_KEY) || modes.STANDARD;
|
|
7
|
+
|
|
8
|
+
// Apply mode to document
|
|
9
|
+
function applyMode(mode) {
|
|
10
|
+
document.documentElement.setAttribute('data-user-mode', mode);
|
|
11
|
+
localStorage.setItem(MODE_KEY, mode);
|
|
12
|
+
|
|
13
|
+
// Update toggle button if exists
|
|
14
|
+
const toggleBtn = document.getElementById('mode-toggle');
|
|
15
|
+
if (toggleBtn) {
|
|
16
|
+
const isAdvanced = mode === modes.ADVANCED;
|
|
17
|
+
toggleBtn.classList.toggle('is-advanced', isAdvanced);
|
|
18
|
+
toggleBtn.setAttribute('aria-label', isAdvanced ? 'Switch to Standard Mode' : 'Switch to Advanced Mode');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Dispatch event for other components
|
|
22
|
+
window.dispatchEvent(new CustomEvent('aztomiq-mode-change', { detail: { mode } }));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Initial apply
|
|
26
|
+
applyMode(currentMode);
|
|
27
|
+
|
|
28
|
+
// Expose to window
|
|
29
|
+
window.AZtomiqMode = {
|
|
30
|
+
get: () => currentMode,
|
|
31
|
+
set: (mode) => {
|
|
32
|
+
currentMode = mode;
|
|
33
|
+
applyMode(mode);
|
|
34
|
+
},
|
|
35
|
+
toggle: () => {
|
|
36
|
+
const newMode = currentMode === modes.STANDARD ? modes.ADVANCED : modes.STANDARD;
|
|
37
|
+
window.AZtomiqMode.set(newMode);
|
|
38
|
+
},
|
|
39
|
+
MODES: modes
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// Wait for DOM to attach listener
|
|
43
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
44
|
+
const toggleBtn = document.getElementById('mode-toggle');
|
|
45
|
+
if (toggleBtn) {
|
|
46
|
+
toggleBtn.addEventListener('click', (e) => {
|
|
47
|
+
e.preventDefault();
|
|
48
|
+
window.AZtomiqMode.toggle();
|
|
49
|
+
});
|
|
50
|
+
// Re-apply to ensure UI is in sync
|
|
51
|
+
applyMode(currentMode);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
})();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var QRCode; !function () { function a(a) { this.mode = c.MODE_8BIT_BYTE, this.data = a, this.parsedData = []; for (var b = [], d = 0, e = this.data.length; e > d; d++) { var f = this.data.charCodeAt(d); f > 65536 ? (b[0] = 240 | (1835008 & f) >>> 18, b[1] = 128 | (258048 & f) >>> 12, b[2] = 128 | (4032 & f) >>> 6, b[3] = 128 | 63 & f) : f > 2048 ? (b[0] = 224 | (61440 & f) >>> 12, b[1] = 128 | (4032 & f) >>> 6, b[2] = 128 | 63 & f) : f > 128 ? (b[0] = 192 | (1984 & f) >>> 6, b[1] = 128 | 63 & f) : b[0] = f, this.parsedData = this.parsedData.concat(b) } this.parsedData.length != this.data.length && (this.parsedData.unshift(191), this.parsedData.unshift(187), this.parsedData.unshift(239)) } function b(a, b) { this.typeNumber = a, this.errorCorrectLevel = b, this.modules = null, this.moduleCount = 0, this.dataCache = null, this.dataList = [] } function i(a, b) { if (void 0 == a.length) throw new Error(a.length + "/" + b); for (var c = 0; c < a.length && 0 == a[c];)c++; this.num = new Array(a.length - c + b); for (var d = 0; d < a.length - c; d++)this.num[d] = a[d + c] } function j(a, b) { this.totalCount = a, this.dataCount = b } function k() { this.buffer = [], this.length = 0 } function m() { return "undefined" != typeof CanvasRenderingContext2D } function n() { var a = !1, b = navigator.userAgent; return /android/i.test(b) && (a = !0, aMat = b.toString().match(/android ([0-9]\.[0-9])/i), aMat && aMat[1] && (a = parseFloat(aMat[1]))), a } function r(a, b) { for (var c = 1, e = s(a), f = 0, g = l.length; g >= f; f++) { var h = 0; switch (b) { case d.L: h = l[f][0]; break; case d.M: h = l[f][1]; break; case d.Q: h = l[f][2]; break; case d.H: h = l[f][3] }if (h >= e) break; c++ } if (c > l.length) throw new Error("Too long data"); return c } function s(a) { var b = encodeURI(a).toString().replace(/\%[0-9a-fA-F]{2}/g, "a"); return b.length + (b.length != a ? 3 : 0) } a.prototype = { getLength: function () { return this.parsedData.length }, write: function (a) { for (var b = 0, c = this.parsedData.length; c > b; b++)a.put(this.parsedData[b], 8) } }, b.prototype = { addData: function (b) { var c = new a(b); this.dataList.push(c), this.dataCache = null }, isDark: function (a, b) { if (0 > a || this.moduleCount <= a || 0 > b || this.moduleCount <= b) throw new Error(a + "," + b); return this.modules[a][b] }, getModuleCount: function () { return this.moduleCount }, make: function () { this.makeImpl(!1, this.getBestMaskPattern()) }, makeImpl: function (a, c) { this.moduleCount = 4 * this.typeNumber + 17, this.modules = new Array(this.moduleCount); for (var d = 0; d < this.moduleCount; d++) { this.modules[d] = new Array(this.moduleCount); for (var e = 0; e < this.moduleCount; e++)this.modules[d][e] = null } this.setupPositionProbePattern(0, 0), this.setupPositionProbePattern(this.moduleCount - 7, 0), this.setupPositionProbePattern(0, this.moduleCount - 7), this.setupPositionAdjustPattern(), this.setupTimingPattern(), this.setupTypeInfo(a, c), this.typeNumber >= 7 && this.setupTypeNumber(a), null == this.dataCache && (this.dataCache = b.createData(this.typeNumber, this.errorCorrectLevel, this.dataList)), this.mapData(this.dataCache, c) }, setupPositionProbePattern: function (a, b) { for (var c = -1; 7 >= c; c++)if (!(-1 >= a + c || this.moduleCount <= a + c)) for (var d = -1; 7 >= d; d++)-1 >= b + d || this.moduleCount <= b + d || (this.modules[a + c][b + d] = c >= 0 && 6 >= c && (0 == d || 6 == d) || d >= 0 && 6 >= d && (0 == c || 6 == c) || c >= 2 && 4 >= c && d >= 2 && 4 >= d ? !0 : !1) }, getBestMaskPattern: function () { for (var a = 0, b = 0, c = 0; 8 > c; c++) { this.makeImpl(!0, c); var d = f.getLostPoint(this); (0 == c || a > d) && (a = d, b = c) } return b }, createMovieClip: function (a, b, c) { var d = a.createEmptyMovieClip(b, c), e = 1; this.make(); for (var f = 0; f < this.modules.length; f++)for (var g = f * e, h = 0; h < this.modules[f].length; h++) { var i = h * e, j = this.modules[f][h]; j && (d.beginFill(0, 100), d.moveTo(i, g), d.lineTo(i + e, g), d.lineTo(i + e, g + e), d.lineTo(i, g + e), d.endFill()) } return d }, setupTimingPattern: function () { for (var a = 8; a < this.moduleCount - 8; a++)null == this.modules[a][6] && (this.modules[a][6] = 0 == a % 2); for (var b = 8; b < this.moduleCount - 8; b++)null == this.modules[6][b] && (this.modules[6][b] = 0 == b % 2) }, setupPositionAdjustPattern: function () { for (var a = f.getPatternPosition(this.typeNumber), b = 0; b < a.length; b++)for (var c = 0; c < a.length; c++) { var d = a[b], e = a[c]; if (null == this.modules[d][e]) for (var g = -2; 2 >= g; g++)for (var h = -2; 2 >= h; h++)this.modules[d + g][e + h] = -2 == g || 2 == g || -2 == h || 2 == h || 0 == g && 0 == h ? !0 : !1 } }, setupTypeNumber: function (a) { for (var b = f.getBCHTypeNumber(this.typeNumber), c = 0; 18 > c; c++) { var d = !a && 1 == (1 & b >> c); this.modules[Math.floor(c / 3)][c % 3 + this.moduleCount - 8 - 3] = d } for (var c = 0; 18 > c; c++) { var d = !a && 1 == (1 & b >> c); this.modules[c % 3 + this.moduleCount - 8 - 3][Math.floor(c / 3)] = d } }, setupTypeInfo: function (a, b) { for (var c = this.errorCorrectLevel << 3 | b, d = f.getBCHTypeInfo(c), e = 0; 15 > e; e++) { var g = !a && 1 == (1 & d >> e); 6 > e ? this.modules[e][8] = g : 8 > e ? this.modules[e + 1][8] = g : this.modules[this.moduleCount - 15 + e][8] = g } for (var e = 0; 15 > e; e++) { var g = !a && 1 == (1 & d >> e); 8 > e ? this.modules[8][this.moduleCount - e - 1] = g : 9 > e ? this.modules[8][15 - e - 1 + 1] = g : this.modules[8][15 - e - 1] = g } this.modules[this.moduleCount - 8][8] = !a }, mapData: function (a, b) { for (var c = -1, d = this.moduleCount - 1, e = 7, g = 0, h = this.moduleCount - 1; h > 0; h -= 2)for (6 == h && h--; ;) { for (var i = 0; 2 > i; i++)if (null == this.modules[d][h - i]) { var j = !1; g < a.length && (j = 1 == (1 & a[g] >>> e)); var k = f.getMask(b, d, h - i); k && (j = !j), this.modules[d][h - i] = j, e--, -1 == e && (g++, e = 7) } if (d += c, 0 > d || this.moduleCount <= d) { d -= c, c = -c; break } } } }, b.PAD0 = 236, b.PAD1 = 17, b.createData = function (a, c, d) { for (var e = j.getRSBlocks(a, c), g = new k, h = 0; h < d.length; h++) { var i = d[h]; g.put(i.mode, 4), g.put(i.getLength(), f.getLengthInBits(i.mode, a)), i.write(g) } for (var l = 0, h = 0; h < e.length; h++)l += e[h].dataCount; if (g.getLengthInBits() > 8 * l) throw new Error("code length overflow. (" + g.getLengthInBits() + ">" + 8 * l + ")"); for (g.getLengthInBits() + 4 <= 8 * l && g.put(0, 4); 0 != g.getLengthInBits() % 8;)g.putBit(!1); for (; ;) { if (g.getLengthInBits() >= 8 * l) break; if (g.put(b.PAD0, 8), g.getLengthInBits() >= 8 * l) break; g.put(b.PAD1, 8) } return b.createBytes(g, e) }, b.createBytes = function (a, b) { for (var c = 0, d = 0, e = 0, g = new Array(b.length), h = new Array(b.length), j = 0; j < b.length; j++) { var k = b[j].dataCount, l = b[j].totalCount - k; d = Math.max(d, k), e = Math.max(e, l), g[j] = new Array(k); for (var m = 0; m < g[j].length; m++)g[j][m] = 255 & a.buffer[m + c]; c += k; var n = f.getErrorCorrectPolynomial(l), o = new i(g[j], n.getLength() - 1), p = o.mod(n); h[j] = new Array(n.getLength() - 1); for (var m = 0; m < h[j].length; m++) { var q = m + p.getLength() - h[j].length; h[j][m] = q >= 0 ? p.get(q) : 0 } } for (var r = 0, m = 0; m < b.length; m++)r += b[m].totalCount; for (var s = new Array(r), t = 0, m = 0; d > m; m++)for (var j = 0; j < b.length; j++)m < g[j].length && (s[t++] = g[j][m]); for (var m = 0; e > m; m++)for (var j = 0; j < b.length; j++)m < h[j].length && (s[t++] = h[j][m]); return s }; for (var c = { MODE_NUMBER: 1, MODE_ALPHA_NUM: 2, MODE_8BIT_BYTE: 4, MODE_KANJI: 8 }, d = { L: 1, M: 0, Q: 3, H: 2 }, e = { PATTERN000: 0, PATTERN001: 1, PATTERN010: 2, PATTERN011: 3, PATTERN100: 4, PATTERN101: 5, PATTERN110: 6, PATTERN111: 7 }, f = { PATTERN_POSITION_TABLE: [[], [6, 18], [6, 22], [6, 26], [6, 30], [6, 34], [6, 22, 38], [6, 24, 42], [6, 26, 46], [6, 28, 50], [6, 30, 54], [6, 32, 58], [6, 34, 62], [6, 26, 46, 66], [6, 26, 48, 70], [6, 26, 50, 74], [6, 30, 54, 78], [6, 30, 56, 82], [6, 30, 58, 86], [6, 34, 62, 90], [6, 28, 50, 72, 94], [6, 26, 50, 74, 98], [6, 30, 54, 78, 102], [6, 28, 54, 80, 106], [6, 32, 58, 84, 110], [6, 30, 58, 86, 114], [6, 34, 62, 90, 118], [6, 26, 50, 74, 98, 122], [6, 30, 54, 78, 102, 126], [6, 26, 52, 78, 104, 130], [6, 30, 56, 82, 108, 134], [6, 34, 60, 86, 112, 138], [6, 30, 58, 86, 114, 142], [6, 34, 62, 90, 118, 146], [6, 30, 54, 78, 102, 126, 150], [6, 24, 50, 76, 102, 128, 154], [6, 28, 54, 80, 106, 132, 158], [6, 32, 58, 84, 110, 136, 162], [6, 26, 54, 82, 110, 138, 166], [6, 30, 58, 86, 114, 142, 170]], G15: 1335, G18: 7973, G15_MASK: 21522, getBCHTypeInfo: function (a) { for (var b = a << 10; f.getBCHDigit(b) - f.getBCHDigit(f.G15) >= 0;)b ^= f.G15 << f.getBCHDigit(b) - f.getBCHDigit(f.G15); return (a << 10 | b) ^ f.G15_MASK }, getBCHTypeNumber: function (a) { for (var b = a << 12; f.getBCHDigit(b) - f.getBCHDigit(f.G18) >= 0;)b ^= f.G18 << f.getBCHDigit(b) - f.getBCHDigit(f.G18); return a << 12 | b }, getBCHDigit: function (a) { for (var b = 0; 0 != a;)b++, a >>>= 1; return b }, getPatternPosition: function (a) { return f.PATTERN_POSITION_TABLE[a - 1] }, getMask: function (a, b, c) { switch (a) { case e.PATTERN000: return 0 == (b + c) % 2; case e.PATTERN001: return 0 == b % 2; case e.PATTERN010: return 0 == c % 3; case e.PATTERN011: return 0 == (b + c) % 3; case e.PATTERN100: return 0 == (Math.floor(b / 2) + Math.floor(c / 3)) % 2; case e.PATTERN101: return 0 == b * c % 2 + b * c % 3; case e.PATTERN110: return 0 == (b * c % 2 + b * c % 3) % 2; case e.PATTERN111: return 0 == (b * c % 3 + (b + c) % 2) % 2; default: throw new Error("bad maskPattern:" + a) } }, getErrorCorrectPolynomial: function (a) { for (var b = new i([1], 0), c = 0; a > c; c++)b = b.multiply(new i([1, g.gexp(c)], 0)); return b }, getLengthInBits: function (a, b) { if (b >= 1 && 10 > b) switch (a) { case c.MODE_NUMBER: return 10; case c.MODE_ALPHA_NUM: return 9; case c.MODE_8BIT_BYTE: return 8; case c.MODE_KANJI: return 8; default: throw new Error("mode:" + a) } else if (27 > b) switch (a) { case c.MODE_NUMBER: return 12; case c.MODE_ALPHA_NUM: return 11; case c.MODE_8BIT_BYTE: return 16; case c.MODE_KANJI: return 10; default: throw new Error("mode:" + a) } else { if (!(41 > b)) throw new Error("type:" + b); switch (a) { case c.MODE_NUMBER: return 14; case c.MODE_ALPHA_NUM: return 13; case c.MODE_8BIT_BYTE: return 16; case c.MODE_KANJI: return 12; default: throw new Error("mode:" + a) } } }, getLostPoint: function (a) { for (var b = a.getModuleCount(), c = 0, d = 0; b > d; d++)for (var e = 0; b > e; e++) { for (var f = 0, g = a.isDark(d, e), h = -1; 1 >= h; h++)if (!(0 > d + h || d + h >= b)) for (var i = -1; 1 >= i; i++)0 > e + i || e + i >= b || (0 != h || 0 != i) && g == a.isDark(d + h, e + i) && f++; f > 5 && (c += 3 + f - 5) } for (var d = 0; b - 1 > d; d++)for (var e = 0; b - 1 > e; e++) { var j = 0; a.isDark(d, e) && j++, a.isDark(d + 1, e) && j++, a.isDark(d, e + 1) && j++, a.isDark(d + 1, e + 1) && j++, (0 == j || 4 == j) && (c += 3) } for (var d = 0; b > d; d++)for (var e = 0; b - 6 > e; e++)a.isDark(d, e) && !a.isDark(d, e + 1) && a.isDark(d, e + 2) && a.isDark(d, e + 3) && a.isDark(d, e + 4) && !a.isDark(d, e + 5) && a.isDark(d, e + 6) && (c += 40); for (var e = 0; b > e; e++)for (var d = 0; b - 6 > d; d++)a.isDark(d, e) && !a.isDark(d + 1, e) && a.isDark(d + 2, e) && a.isDark(d + 3, e) && a.isDark(d + 4, e) && !a.isDark(d + 5, e) && a.isDark(d + 6, e) && (c += 40); for (var k = 0, e = 0; b > e; e++)for (var d = 0; b > d; d++)a.isDark(d, e) && k++; var l = Math.abs(100 * k / b / b - 50) / 5; return c += 10 * l } }, g = { glog: function (a) { if (1 > a) throw new Error("glog(" + a + ")"); return g.LOG_TABLE[a] }, gexp: function (a) { for (; 0 > a;)a += 255; for (; a >= 256;)a -= 255; return g.EXP_TABLE[a] }, EXP_TABLE: new Array(256), LOG_TABLE: new Array(256) }, h = 0; 8 > h; h++)g.EXP_TABLE[h] = 1 << h; for (var h = 8; 256 > h; h++)g.EXP_TABLE[h] = g.EXP_TABLE[h - 4] ^ g.EXP_TABLE[h - 5] ^ g.EXP_TABLE[h - 6] ^ g.EXP_TABLE[h - 8]; for (var h = 0; 255 > h; h++)g.LOG_TABLE[g.EXP_TABLE[h]] = h; i.prototype = { get: function (a) { return this.num[a] }, getLength: function () { return this.num.length }, multiply: function (a) { for (var b = new Array(this.getLength() + a.getLength() - 1), c = 0; c < this.getLength(); c++)for (var d = 0; d < a.getLength(); d++)b[c + d] ^= g.gexp(g.glog(this.get(c)) + g.glog(a.get(d))); return new i(b, 0) }, mod: function (a) { if (this.getLength() - a.getLength() < 0) return this; for (var b = g.glog(this.get(0)) - g.glog(a.get(0)), c = new Array(this.getLength()), d = 0; d < this.getLength(); d++)c[d] = this.get(d); for (var d = 0; d < a.getLength(); d++)c[d] ^= g.gexp(g.glog(a.get(d)) + b); return new i(c, 0).mod(a) } }, j.RS_BLOCK_TABLE = [[1, 26, 19], [1, 26, 16], [1, 26, 13], [1, 26, 9], [1, 44, 34], [1, 44, 28], [1, 44, 22], [1, 44, 16], [1, 70, 55], [1, 70, 44], [2, 35, 17], [2, 35, 13], [1, 100, 80], [2, 50, 32], [2, 50, 24], [4, 25, 9], [1, 134, 108], [2, 67, 43], [2, 33, 15, 2, 34, 16], [2, 33, 11, 2, 34, 12], [2, 86, 68], [4, 43, 27], [4, 43, 19], [4, 43, 15], [2, 98, 78], [4, 49, 31], [2, 32, 14, 4, 33, 15], [4, 39, 13, 1, 40, 14], [2, 121, 97], [2, 60, 38, 2, 61, 39], [4, 40, 18, 2, 41, 19], [4, 40, 14, 2, 41, 15], [2, 146, 116], [3, 58, 36, 2, 59, 37], [4, 36, 16, 4, 37, 17], [4, 36, 12, 4, 37, 13], [2, 86, 68, 2, 87, 69], [4, 69, 43, 1, 70, 44], [6, 43, 19, 2, 44, 20], [6, 43, 15, 2, 44, 16], [4, 101, 81], [1, 80, 50, 4, 81, 51], [4, 50, 22, 4, 51, 23], [3, 36, 12, 8, 37, 13], [2, 116, 92, 2, 117, 93], [6, 58, 36, 2, 59, 37], [4, 46, 20, 6, 47, 21], [7, 42, 14, 4, 43, 15], [4, 133, 107], [8, 59, 37, 1, 60, 38], [8, 44, 20, 4, 45, 21], [12, 33, 11, 4, 34, 12], [3, 145, 115, 1, 146, 116], [4, 64, 40, 5, 65, 41], [11, 36, 16, 5, 37, 17], [11, 36, 12, 5, 37, 13], [5, 109, 87, 1, 110, 88], [5, 65, 41, 5, 66, 42], [5, 54, 24, 7, 55, 25], [11, 36, 12], [5, 122, 98, 1, 123, 99], [7, 73, 45, 3, 74, 46], [15, 43, 19, 2, 44, 20], [3, 45, 15, 13, 46, 16], [1, 135, 107, 5, 136, 108], [10, 74, 46, 1, 75, 47], [1, 50, 22, 15, 51, 23], [2, 42, 14, 17, 43, 15], [5, 150, 120, 1, 151, 121], [9, 69, 43, 4, 70, 44], [17, 50, 22, 1, 51, 23], [2, 42, 14, 19, 43, 15], [3, 141, 113, 4, 142, 114], [3, 70, 44, 11, 71, 45], [17, 47, 21, 4, 48, 22], [9, 39, 13, 16, 40, 14], [3, 135, 107, 5, 136, 108], [3, 67, 41, 13, 68, 42], [15, 54, 24, 5, 55, 25], [15, 43, 15, 10, 44, 16], [4, 144, 116, 4, 145, 117], [17, 68, 42], [17, 50, 22, 6, 51, 23], [19, 46, 16, 6, 47, 17], [2, 139, 111, 7, 140, 112], [17, 74, 46], [7, 54, 24, 16, 55, 25], [34, 37, 13], [4, 151, 121, 5, 152, 122], [4, 75, 47, 14, 76, 48], [11, 54, 24, 14, 55, 25], [16, 45, 15, 14, 46, 16], [6, 147, 117, 4, 148, 118], [6, 73, 45, 14, 74, 46], [11, 54, 24, 16, 55, 25], [30, 46, 16, 2, 47, 17], [8, 132, 106, 4, 133, 107], [8, 75, 47, 13, 76, 48], [7, 54, 24, 22, 55, 25], [22, 45, 15, 13, 46, 16], [10, 142, 114, 2, 143, 115], [19, 74, 46, 4, 75, 47], [28, 50, 22, 6, 51, 23], [33, 46, 16, 4, 47, 17], [8, 152, 122, 4, 153, 123], [22, 73, 45, 3, 74, 46], [8, 53, 23, 26, 54, 24], [12, 45, 15, 28, 46, 16], [3, 147, 117, 10, 148, 118], [3, 73, 45, 23, 74, 46], [4, 54, 24, 31, 55, 25], [11, 45, 15, 31, 46, 16], [7, 146, 116, 7, 147, 117], [21, 73, 45, 7, 74, 46], [1, 53, 23, 37, 54, 24], [19, 45, 15, 26, 46, 16], [5, 145, 115, 10, 146, 116], [19, 75, 47, 10, 76, 48], [15, 54, 24, 25, 55, 25], [23, 45, 15, 25, 46, 16], [13, 145, 115, 3, 146, 116], [2, 74, 46, 29, 75, 47], [42, 54, 24, 1, 55, 25], [23, 45, 15, 28, 46, 16], [17, 145, 115], [10, 74, 46, 23, 75, 47], [10, 54, 24, 35, 55, 25], [19, 45, 15, 35, 46, 16], [17, 145, 115, 1, 146, 116], [14, 74, 46, 21, 75, 47], [29, 54, 24, 19, 55, 25], [11, 45, 15, 46, 46, 16], [13, 145, 115, 6, 146, 116], [14, 74, 46, 23, 75, 47], [44, 54, 24, 7, 55, 25], [59, 46, 16, 1, 47, 17], [12, 151, 121, 7, 152, 122], [12, 75, 47, 26, 76, 48], [39, 54, 24, 14, 55, 25], [22, 45, 15, 41, 46, 16], [6, 151, 121, 14, 152, 122], [6, 75, 47, 34, 76, 48], [46, 54, 24, 10, 55, 25], [2, 45, 15, 64, 46, 16], [17, 152, 122, 4, 153, 123], [29, 74, 46, 14, 75, 47], [49, 54, 24, 10, 55, 25], [24, 45, 15, 46, 46, 16], [4, 152, 122, 18, 153, 123], [13, 74, 46, 32, 75, 47], [48, 54, 24, 14, 55, 25], [42, 45, 15, 32, 46, 16], [20, 147, 117, 4, 148, 118], [40, 75, 47, 7, 76, 48], [43, 54, 24, 22, 55, 25], [10, 45, 15, 67, 46, 16], [19, 148, 118, 6, 149, 119], [18, 75, 47, 31, 76, 48], [34, 54, 24, 34, 55, 25], [20, 45, 15, 61, 46, 16]], j.getRSBlocks = function (a, b) { var c = j.getRsBlockTable(a, b); if (void 0 == c) throw new Error("bad rs block @ typeNumber:" + a + "/errorCorrectLevel:" + b); for (var d = c.length / 3, e = [], f = 0; d > f; f++)for (var g = c[3 * f + 0], h = c[3 * f + 1], i = c[3 * f + 2], k = 0; g > k; k++)e.push(new j(h, i)); return e }, j.getRsBlockTable = function (a, b) { switch (b) { case d.L: return j.RS_BLOCK_TABLE[4 * (a - 1) + 0]; case d.M: return j.RS_BLOCK_TABLE[4 * (a - 1) + 1]; case d.Q: return j.RS_BLOCK_TABLE[4 * (a - 1) + 2]; case d.H: return j.RS_BLOCK_TABLE[4 * (a - 1) + 3]; default: return void 0 } }, k.prototype = { get: function (a) { var b = Math.floor(a / 8); return 1 == (1 & this.buffer[b] >>> 7 - a % 8) }, put: function (a, b) { for (var c = 0; b > c; c++)this.putBit(1 == (1 & a >>> b - c - 1)) }, getLengthInBits: function () { return this.length }, putBit: function (a) { var b = Math.floor(this.length / 8); this.buffer.length <= b && this.buffer.push(0), a && (this.buffer[b] |= 128 >>> this.length % 8), this.length++ } }; var l = [[17, 14, 11, 7], [32, 26, 20, 14], [53, 42, 32, 24], [78, 62, 46, 34], [106, 84, 60, 44], [134, 106, 74, 58], [154, 122, 86, 64], [192, 152, 108, 84], [230, 180, 130, 98], [271, 213, 151, 119], [321, 251, 177, 137], [367, 287, 203, 155], [425, 331, 241, 177], [458, 362, 258, 194], [520, 412, 292, 220], [586, 450, 322, 250], [644, 504, 364, 280], [718, 560, 394, 310], [792, 624, 442, 338], [858, 666, 482, 382], [929, 711, 509, 403], [1003, 779, 565, 439], [1091, 857, 611, 461], [1171, 911, 661, 511], [1273, 997, 715, 535], [1367, 1059, 751, 593], [1465, 1125, 805, 625], [1528, 1190, 868, 658], [1628, 1264, 908, 698], [1732, 1370, 982, 742], [1840, 1452, 1030, 790], [1952, 1538, 1112, 842], [2068, 1628, 1168, 898], [2188, 1722, 1228, 958], [2303, 1809, 1283, 983], [2431, 1911, 1351, 1051], [2563, 1989, 1423, 1093], [2699, 2099, 1499, 1139], [2809, 2213, 1579, 1219], [2953, 2331, 1663, 1273]], o = function () { var a = function (a, b) { this._el = a, this._htOption = b }; return a.prototype.draw = function (a) { function g(a, b) { var c = document.createElementNS("http://www.w3.org/2000/svg", a); for (var d in b) b.hasOwnProperty(d) && c.setAttribute(d, b[d]); return c } var b = this._htOption, c = this._el, d = a.getModuleCount(); Math.floor(b.width / d), Math.floor(b.height / d), this.clear(); var h = g("svg", { viewBox: "0 0 " + String(d) + " " + String(d), width: "100%", height: "100%", fill: b.colorLight }); h.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink"), c.appendChild(h), h.appendChild(g("rect", { fill: b.colorDark, width: "1", height: "1", id: "template" })); for (var i = 0; d > i; i++)for (var j = 0; d > j; j++)if (a.isDark(i, j)) { var k = g("use", { x: String(i), y: String(j) }); k.setAttributeNS("http://www.w3.org/1999/xlink", "href", "#template"), h.appendChild(k) } }, a.prototype.clear = function () { for (; this._el.hasChildNodes();)this._el.removeChild(this._el.lastChild) }, a }(), p = "svg" === document.documentElement.tagName.toLowerCase(), q = p ? o : m() ? function () { function a() { this._elImage.src = this._elCanvas.toDataURL("image/png"), this._elImage.style.display = "block", this._elCanvas.style.display = "none" } function d(a, b) { var c = this; if (c._fFail = b, c._fSuccess = a, null === c._bSupportDataURI) { var d = document.createElement("img"), e = function () { c._bSupportDataURI = !1, c._fFail && _fFail.call(c) }, f = function () { c._bSupportDataURI = !0, c._fSuccess && c._fSuccess.call(c) }; return d.onabort = e, d.onerror = e, d.onload = f, d.src = "data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==", void 0 } c._bSupportDataURI === !0 && c._fSuccess ? c._fSuccess.call(c) : c._bSupportDataURI === !1 && c._fFail && c._fFail.call(c) } if (this._android && this._android <= 2.1) { var b = 1 / window.devicePixelRatio, c = CanvasRenderingContext2D.prototype.drawImage; CanvasRenderingContext2D.prototype.drawImage = function (a, d, e, f, g, h, i, j) { if ("nodeName" in a && /img/i.test(a.nodeName)) for (var l = arguments.length - 1; l >= 1; l--)arguments[l] = arguments[l] * b; else "undefined" == typeof j && (arguments[1] *= b, arguments[2] *= b, arguments[3] *= b, arguments[4] *= b); c.apply(this, arguments) } } var e = function (a, b) { this._bIsPainted = !1, this._android = n(), this._htOption = b, this._elCanvas = document.createElement("canvas"), this._elCanvas.width = b.width, this._elCanvas.height = b.height, a.appendChild(this._elCanvas), this._el = a, this._oContext = this._elCanvas.getContext("2d"), this._bIsPainted = !1, this._elImage = document.createElement("img"), this._elImage.style.display = "none", this._el.appendChild(this._elImage), this._bSupportDataURI = null }; return e.prototype.draw = function (a) { var b = this._elImage, c = this._oContext, d = this._htOption, e = a.getModuleCount(), f = d.width / e, g = d.height / e, h = Math.round(f), i = Math.round(g); b.style.display = "none", this.clear(); for (var j = 0; e > j; j++)for (var k = 0; e > k; k++) { var l = a.isDark(j, k), m = k * f, n = j * g; c.strokeStyle = l ? d.colorDark : d.colorLight, c.lineWidth = 1, c.fillStyle = l ? d.colorDark : d.colorLight, c.fillRect(m, n, f, g), c.strokeRect(Math.floor(m) + .5, Math.floor(n) + .5, h, i), c.strokeRect(Math.ceil(m) - .5, Math.ceil(n) - .5, h, i) } this._bIsPainted = !0 }, e.prototype.makeImage = function () { this._bIsPainted && d.call(this, a) }, e.prototype.isPainted = function () { return this._bIsPainted }, e.prototype.clear = function () { this._oContext.clearRect(0, 0, this._elCanvas.width, this._elCanvas.height), this._bIsPainted = !1 }, e.prototype.round = function (a) { return a ? Math.floor(1e3 * a) / 1e3 : a }, e }() : function () { var a = function (a, b) { this._el = a, this._htOption = b }; return a.prototype.draw = function (a) { for (var b = this._htOption, c = this._el, d = a.getModuleCount(), e = Math.floor(b.width / d), f = Math.floor(b.height / d), g = ['<table style="border:0;border-collapse:collapse;">'], h = 0; d > h; h++) { g.push("<tr>"); for (var i = 0; d > i; i++)g.push('<td style="border:0;border-collapse:collapse;padding:0;margin:0;width:' + e + "px;height:" + f + "px;background-color:" + (a.isDark(h, i) ? b.colorDark : b.colorLight) + ';"></td>'); g.push("</tr>") } g.push("</table>"), c.innerHTML = g.join(""); var j = c.childNodes[0], k = (b.width - j.offsetWidth) / 2, l = (b.height - j.offsetHeight) / 2; k > 0 && l > 0 && (j.style.margin = l + "px " + k + "px") }, a.prototype.clear = function () { this._el.innerHTML = "" }, a }(); QRCode = function (a, b) { if (this._htOption = { width: 256, height: 256, typeNumber: 4, colorDark: "#000000", colorLight: "#ffffff", correctLevel: d.H }, "string" == typeof b && (b = { text: b }), b) for (var c in b) this._htOption[c] = b[c]; "string" == typeof a && (a = document.getElementById(a)), this._android = n(), this._el = a, this._oQRCode = null, this._oDrawing = new q(this._el, this._htOption), this._htOption.text && this.makeCode(this._htOption.text) }, QRCode.prototype.makeCode = function (a) { this._oQRCode = new b(r(a, this._htOption.correctLevel), this._htOption.correctLevel), this._oQRCode.addData(a), this._oQRCode.make(), this._el.title = a, this._oDrawing.draw(this._oQRCode), this.makeImage() }, QRCode.prototype.makeImage = function () { "function" == typeof this._oDrawing.makeImage && (!this._android || this._android >= 3) && this._oDrawing.makeImage() }, QRCode.prototype.clear = function () { this._oDrawing.clear() }, QRCode.CorrectLevel = d }();
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
meta:
|
|
2
|
+
title: AZtomiq - Modern Framework
|
|
3
|
+
description: "A comprehensive A-Z framework for building utility sites."
|
|
4
|
+
about:
|
|
5
|
+
title: About
|
|
6
|
+
intro_h2: "👋 Hello!"
|
|
7
|
+
intro_p1: "<strong>AZtomiq</strong> is an online utility toolkit built with a focus on: <strong>Simplicity - Speed - Privacy - Convenience</strong>."
|
|
8
|
+
intro_p2: "We understand that when you need to calculate finance, format JSON, or <strong>quickly test code (Playground)</strong>, you want a focused, professional, and instant environment."
|
|
9
|
+
why_h3: "🚀 Why choose AZtomiq?"
|
|
10
|
+
why_li1: "<strong>Free Forever:</strong> All tools are completely free."
|
|
11
|
+
why_li2: "<strong>Absolute Privacy:</strong> All processing happens in your browser (Client-side). No data is sent to our servers."
|
|
12
|
+
why_li3: "<strong>User-Friendly Interface:</strong> Clean, intuitive design with Dark Mode support."
|
|
13
|
+
contact_h3: "📬 Contact"
|
|
14
|
+
contact_p: "For any feedback, bug reports, or feature suggestions, please contact us via email:"
|
|
15
|
+
privacy:
|
|
16
|
+
title: Privacy Policy
|
|
17
|
+
last_updated: "Last updated: 12/23/2025"
|
|
18
|
+
section1_h3: "1. Data Collection"
|
|
19
|
+
section1_p: "At <strong>AZtomiq</strong>, your privacy is our top priority. <strong>We do NOT collect, store, or share any personal data you enter into the tools.</strong>"
|
|
20
|
+
section1_li1: "Calculation data for tax, salary, BMI... is only processed on your browser."
|
|
21
|
+
section1_li2: "<strong>Web Playground:</strong> Any code you write and run is executed locally (client-side). Our servers do not store your source code."
|
|
22
|
+
section1_li3: "When you close the tab or reload the page, temporary data disappears (unless you choose to save it to LocalStorage History)."
|
|
23
|
+
section2_h3: "2. Local Storage & Cookies"
|
|
24
|
+
section2_p: "We use <strong>Local Storage</strong> for the following purposes:"
|
|
25
|
+
section2_li1: "Saving theme preferences (Dark/Light mode)."
|
|
26
|
+
section2_li2: "Saving calculation history (if enabled). This data remains entirely on your device."
|
|
27
|
+
section2_p2: "We do not use Cookies for tracking personal behavior."
|
|
28
|
+
section3_h3: "3. Third-party Services"
|
|
29
|
+
section3_p: "The website may use anonymous analytics to improve performance. These services operate under their own privacy policies."
|
|
30
|
+
section4_h3: "4. Policy Changes"
|
|
31
|
+
section4_p: "We reserve the right to update this policy at any time. Changes will be posted on this page."
|
|
32
|
+
terms:
|
|
33
|
+
title: Terms of Service
|
|
34
|
+
section1_h3: "1. Acceptance of Terms"
|
|
35
|
+
section1_p: "By accessing and using <strong>AZtomiq</strong>, you agree to comply with these terms. If you do not agree, please stop using the service."
|
|
36
|
+
section2_h3: "2. Purpose of Use"
|
|
37
|
+
section2_p: "AZtomiq provides utility tools for reference purposes only."
|
|
38
|
+
section2_li1: "<strong>Financial Tools (Tax, Salary...):</strong> Results are for reference. We strive for accuracy but are not legally responsible for absolute correctness. Consult a professional for important decisions."
|
|
39
|
+
section2_li2: "<strong>Health Tools (BMI...):</strong> Does not replace professional medical advice."
|
|
40
|
+
section2_li3: "<strong>Web Playground:</strong> You are responsible for the code you execute. We provide a sandbox but are not liable for security issues from user-inserted malicious code."
|
|
41
|
+
section3_h3: "3. Disclaimer"
|
|
42
|
+
section3_p: "AZtomiq is provided 'as is'. We do not guarantee uninterrupted service and are not liable for damages arising from website use."
|
|
43
|
+
section4_h3: "4. Copyright"
|
|
44
|
+
section4_p: "Source code and content belong to the developers, except for validly used open-source libraries."
|
|
45
|
+
changelog:
|
|
46
|
+
title: Version History
|
|
47
|
+
common:
|
|
48
|
+
legacy_title: Legacy Version
|
|
49
|
+
legacy_desc: This tool has been integrated into a new version.
|
|
50
|
+
try_master: Try Now
|
|
51
|
+
reset: Reset
|
|
52
|
+
back: Back
|
|
53
|
+
nav:
|
|
54
|
+
home: Home
|
|
55
|
+
menu_categories: Categories
|
|
56
|
+
search_placeholder: "Search... (Ctrl + K)"
|
|
57
|
+
search_no_results: No results found for
|
|
58
|
+
search_title: Search
|
|
59
|
+
changelog_title: Version History
|
|
60
|
+
menu_blog: Articles
|
|
61
|
+
reset: Reset
|
|
62
|
+
how_to_use: How to use
|
|
63
|
+
mode_standard: Standard
|
|
64
|
+
mode_advanced: Advanced
|
|
65
|
+
mode_standard_desc: Standard Mode
|
|
66
|
+
mode_advanced_desc: Advanced Mode
|
|
67
|
+
home:
|
|
68
|
+
hero_title: AZtomiq
|
|
69
|
+
hero_desc: "A to Z • Atomic • Fast"
|
|
70
|
+
favorites: My Favorites
|
|
71
|
+
cats:
|
|
72
|
+
finance:
|
|
73
|
+
title: Finance
|
|
74
|
+
dev:
|
|
75
|
+
title: Developer
|
|
76
|
+
tools:
|
|
77
|
+
title: General
|
|
78
|
+
sort:
|
|
79
|
+
default: Default
|
|
80
|
+
az: Name (A-Z)
|
|
81
|
+
za: Name (Z-A)
|
|
82
|
+
recent: Recently Used
|
|
83
|
+
popular: Most Used
|
|
84
|
+
reset: Reset
|
|
85
|
+
footer:
|
|
86
|
+
about_title: AZtomiq
|
|
87
|
+
about_desc: "A modern framework for building utility sites."
|
|
88
|
+
links_title: Links
|
|
89
|
+
intro: About
|
|
90
|
+
policy: Privacy Policy
|
|
91
|
+
terms: Terms of Service
|
|
92
|
+
changelog: Versions
|
|
93
|
+
copyright: "© 2025. Built with ❤️."
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
meta:
|
|
2
|
+
title: AZtomiq - Nền tảng hiện đại
|
|
3
|
+
description: "Bộ khung A-Z hiện đại để xây dựng trang web tiện ích."
|
|
4
|
+
about:
|
|
5
|
+
title: Giới thiệu
|
|
6
|
+
intro_h2: "👋 Xin chào!"
|
|
7
|
+
intro_p1: "<strong>AZtomiq</strong> là bộ công cụ tiện ích trực tuyến được xây dựng với mục tiêu: <strong>Đơn giản - Nhanh chóng - Riêng tư - Tiện lợi</strong>."
|
|
8
|
+
intro_p2: "Chúng tôi hiểu rằng khi bạn cần tính toán tài chính, format JSON, hay <strong>thử nghiệm code nhanh (Playground)</strong>, bạn muốn có một môi trường làm việc tập trung, chuyên nghiệp và tức thì."
|
|
9
|
+
why_h3: "🚀 Tại sao chọn AZtomiq?"
|
|
10
|
+
why_li1: "<strong>Miễn phí trọn đời:</strong> Tất cả công cụ đều miễn phí."
|
|
11
|
+
why_li2: "<strong>Bảo mật tuyệt đối:</strong> Mọi tính toán diễn ra ngay trên trình duyệt của bạn (Client-side). Không có dữ liệu nào được gửi về máy chủ."
|
|
12
|
+
why_li3: "<strong>Giao diện thân thiện:</strong> Sạch sẽ, dễ nhìn, hỗ trợ Dark Mode."
|
|
13
|
+
contact_h3: "📬 Liên hệ"
|
|
14
|
+
contact_p: "Mọi ý kiến đóng góp, báo lỗi hoặc đề xuất tính năng, vui lòng liên hệ qua email:"
|
|
15
|
+
privacy:
|
|
16
|
+
title: Chính sách bảo mật
|
|
17
|
+
last_updated: "Cập nhật lần cuối: 23/12/2025"
|
|
18
|
+
section1_h3: "1. Thu thập dữ liệu"
|
|
19
|
+
section1_p: "Tại <strong>AZtomiq</strong>, chúng tôi ưu tiên sự riêng tư của bạn lên hàng đầu. <strong>Chúng tôi KHÔNG thu thập, lưu trữ hay chia sẻ bất kỳ dữ liệu cá nhân nào bạn nhập vào các công cụ.</strong>"
|
|
20
|
+
section1_li1: "Dữ liệu tính thuế, lương, BMI... chỉ được xử lý trên trình duyệt của bạn."
|
|
21
|
+
section1_li2: "<strong>Web Playground:</strong> Mọi đoạn mã bạn viết và chạy đều được thực thi cục bộ (client-side) trong trình duyệt. Server của chúng tôi không lưu trữ mã nguồn của bạn."
|
|
22
|
+
section1_li3: "Khi bạn đóng tab hoặc tải lại trang, dữ liệu tạm thời này sẽ biến mất (trừ khi bạn chọn lưu vào LocalStorage)."
|
|
23
|
+
section2_h3: "2. Local Storage & Cookies"
|
|
24
|
+
section2_p: "Chúng tôi sử dụng <strong>Local Storage</strong> (bộ nhớ trình duyệt) cho các mục đích sau:"
|
|
25
|
+
section2_li1: "Lưu tùy chọn giao diện (Dark/Light mode)."
|
|
26
|
+
section2_li2: "Lưu lịch sử tính toán (nếu bạn bật tính năng này). Dữ liệu này nằm hoàn toàn trên thiết bị của bạn."
|
|
27
|
+
section2_p2: "Chúng tôi không sử dụng Cookies để theo dõi hành vi cá nhân."
|
|
28
|
+
section3_h3: "3. Dịch vụ bên thứ ba"
|
|
29
|
+
section3_p: "Website có thể sử dụng các dịch vụ phân tích ẩn danh để cải thiện hiệu suất. Các dịch vụ này hoạt động theo chính sách bảo mật riêng của họ."
|
|
30
|
+
section4_h3: "4. Thay đổi chính sách"
|
|
31
|
+
section4_p: "Chúng tôi có quyền cập nhật chính sách này bất cứ lúc nào. Các thay đổi sẽ được thông báo trên trang này."
|
|
32
|
+
terms:
|
|
33
|
+
title: Điều khoản sử dụng
|
|
34
|
+
section1_h3: "1. Chấp nhận điều khoản"
|
|
35
|
+
section1_p: "Bằng việc truy cập và sử dụng <strong>AZtomiq</strong>, bạn đồng ý tuân thủ các điều khoản sử dụng này. Nếu bạn không đồng ý, vui lòng ngưng sử dụng dịch vụ."
|
|
36
|
+
section2_h3: "2. Mục đích sử dụng"
|
|
37
|
+
section2_p: "AZtomiq cung cấp các công cụ tính toán và tiện ích cho mục đích tham khảo."
|
|
38
|
+
section2_li1: "<strong>Công cụ Tài chính (Thuế, Lương...):</strong> Kết quả tính toán chỉ mang tính chất tham khảo. Chúng tôi nỗ lực cập nhật theo luật mới nhất nhưng không chịu trách nhiệm pháp lý về tính chính xác tuyệt đối. Vui lòng tham khảo ý kiến chuyên gia cho các quyết định quan trọng."
|
|
39
|
+
section2_li2: "<strong>Công cụ Sức khỏe (BMI...):</strong> Không thay thế cho lời khuyên y tế chuyên nghiệp."
|
|
40
|
+
section2_li3: "<strong>Web Playground:</strong> Bạn tự chịu trách nhiệm về mã nguồn bạn thực thi. Chúng tôi cung cấp môi trường chạy an toàn (sandbox) nhưng không chịu trách nhiệm về các vấn đề bảo mật phát sinh từ mã độc do người dùng tự chèn vào."
|
|
41
|
+
section3_h3: "3. Miễn trừ trách nhiệm"
|
|
42
|
+
section3_p: "AZtomiq được cung cấp 'nguyên trạng'. Chúng tôi không cam kết rằng dịch vụ sẽ không bị gián đoạn hoặc không có lỗi. Chúng tôi không chịu trách nhiệm về bất kỳ thiệt hại nào phát sinh từ việc sử dụng các công cụ trên trang web này."
|
|
43
|
+
section4_h3: "4. Bản quyền"
|
|
44
|
+
section4_p: "Mã nguồn và nội dung của AZtomiq thuộc quyền sở hữu của đội ngũ phát triển, trừ các thư viện mã nguồn mở được sử dụng hợp lệ."
|
|
45
|
+
changelog:
|
|
46
|
+
title: Nhật ký thay đổi
|
|
47
|
+
common:
|
|
48
|
+
legacy_title: Phiên bản cũ
|
|
49
|
+
legacy_desc: Công cụ này đã được tích hợp vào phiên bản mới.
|
|
50
|
+
try_master: Thử ngay
|
|
51
|
+
reset: Đặt lại
|
|
52
|
+
back: Quay lại
|
|
53
|
+
nav:
|
|
54
|
+
home: Trang chủ
|
|
55
|
+
menu_categories: Danh mục
|
|
56
|
+
search_placeholder: "Tìm kiếm... (Ctrl + K)"
|
|
57
|
+
search_no_results: Không tìm thấy kết quả cho
|
|
58
|
+
search_title: Tìm kiếm
|
|
59
|
+
changelog_title: Nhật ký thay đổi
|
|
60
|
+
menu_blog: Bài viết
|
|
61
|
+
reset: Đặt lại
|
|
62
|
+
how_to_use: Hướng dẫn sử dụng
|
|
63
|
+
mode_standard: Standard
|
|
64
|
+
mode_advanced: Advanced
|
|
65
|
+
mode_standard_desc: Chế độ Tiêu chuẩn
|
|
66
|
+
mode_advanced_desc: Chế độ Nâng cao
|
|
67
|
+
home:
|
|
68
|
+
hero_title: AZtomiq
|
|
69
|
+
hero_desc: "A to Z • Atomic • Tốc độ"
|
|
70
|
+
favorites: Công cụ yêu thích
|
|
71
|
+
cats:
|
|
72
|
+
finance:
|
|
73
|
+
title: Tài chính
|
|
74
|
+
dev:
|
|
75
|
+
title: Lập trình
|
|
76
|
+
tools:
|
|
77
|
+
title: Tiện ích
|
|
78
|
+
sort:
|
|
79
|
+
default: Mặc định
|
|
80
|
+
az: Tên (A-Z)
|
|
81
|
+
za: Tên (Z-A)
|
|
82
|
+
recent: Vừa xem
|
|
83
|
+
popular: Phổ biến nhất
|
|
84
|
+
reset: Đặt lại
|
|
85
|
+
footer:
|
|
86
|
+
about_title: AZtomiq
|
|
87
|
+
about_desc: "Bộ khung A-Z hiện đại để xây dựng trang web tiện ích."
|
|
88
|
+
links_title: Liên kết
|
|
89
|
+
intro: Giới thiệu
|
|
90
|
+
policy: Chính sách
|
|
91
|
+
terms: Điều khoản
|
|
92
|
+
changelog: Cập nhật
|
|
93
|
+
copyright: "© 2025. Được xây dựng với ❤️."
|