@o2vend/theme-cli 1.0.32

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 (116) hide show
  1. package/README.md +425 -0
  2. package/assets/Logo_o2vend.png +0 -0
  3. package/assets/favicon.png +0 -0
  4. package/assets/logo-white.png +0 -0
  5. package/bin/o2vend +42 -0
  6. package/config/widget-map.json +50 -0
  7. package/lib/commands/check.js +201 -0
  8. package/lib/commands/generate.js +33 -0
  9. package/lib/commands/init.js +214 -0
  10. package/lib/commands/optimize.js +216 -0
  11. package/lib/commands/package.js +208 -0
  12. package/lib/commands/serve.js +105 -0
  13. package/lib/commands/validate.js +191 -0
  14. package/lib/lib/api-client.js +357 -0
  15. package/lib/lib/dev-server.js +2618 -0
  16. package/lib/lib/file-watcher.js +80 -0
  17. package/lib/lib/hot-reload.js +106 -0
  18. package/lib/lib/liquid-engine.js +822 -0
  19. package/lib/lib/liquid-filters.js +671 -0
  20. package/lib/lib/mock-api-server.js +989 -0
  21. package/lib/lib/mock-data.js +1468 -0
  22. package/lib/lib/widget-service.js +321 -0
  23. package/package.json +70 -0
  24. package/test-theme/README.md +27 -0
  25. package/test-theme/assets/async-sections.js +446 -0
  26. package/test-theme/assets/cart-drawer.js +463 -0
  27. package/test-theme/assets/cart-manager.js +223 -0
  28. package/test-theme/assets/checkout-price-handler.js +368 -0
  29. package/test-theme/assets/components.css +4629 -0
  30. package/test-theme/assets/delivery-zone.css +299 -0
  31. package/test-theme/assets/delivery-zone.js +396 -0
  32. package/test-theme/assets/logo.png +0 -0
  33. package/test-theme/assets/sections.css +48 -0
  34. package/test-theme/assets/theme.css +3500 -0
  35. package/test-theme/assets/theme.js +3745 -0
  36. package/test-theme/config/settings_data.json +292 -0
  37. package/test-theme/config/settings_schema.json +1050 -0
  38. package/test-theme/layout/theme.liquid +195 -0
  39. package/test-theme/locales/en.default.json +260 -0
  40. package/test-theme/sections/content-fallback.liquid +53 -0
  41. package/test-theme/sections/content.liquid +57 -0
  42. package/test-theme/sections/footer-fallback.liquid +328 -0
  43. package/test-theme/sections/footer.liquid +278 -0
  44. package/test-theme/sections/header-fallback.liquid +1805 -0
  45. package/test-theme/sections/header.liquid +1145 -0
  46. package/test-theme/sections/hero-fallback.liquid +212 -0
  47. package/test-theme/sections/hero.liquid +136 -0
  48. package/test-theme/snippets/account-sidebar.liquid +200 -0
  49. package/test-theme/snippets/add-to-cart-modal.liquid +484 -0
  50. package/test-theme/snippets/breadcrumbs.liquid +134 -0
  51. package/test-theme/snippets/cart-drawer.liquid +467 -0
  52. package/test-theme/snippets/delivery-zone-city-selector.liquid +79 -0
  53. package/test-theme/snippets/delivery-zone-modal.liquid +337 -0
  54. package/test-theme/snippets/delivery-zone-search.liquid +78 -0
  55. package/test-theme/snippets/icon.liquid +105 -0
  56. package/test-theme/snippets/login-modal.liquid +346 -0
  57. package/test-theme/snippets/mega-menu.liquid +812 -0
  58. package/test-theme/snippets/news-thumbnail.liquid +187 -0
  59. package/test-theme/snippets/pagination.liquid +120 -0
  60. package/test-theme/snippets/price.liquid +92 -0
  61. package/test-theme/snippets/product-card-related.liquid +78 -0
  62. package/test-theme/snippets/product-card-simple.liquid +41 -0
  63. package/test-theme/snippets/product-card.liquid +697 -0
  64. package/test-theme/snippets/rating.liquid +85 -0
  65. package/test-theme/snippets/skeleton-collection-grid.liquid +114 -0
  66. package/test-theme/snippets/skeleton-product-card.liquid +124 -0
  67. package/test-theme/snippets/skeleton-product-grid.liquid +34 -0
  68. package/test-theme/snippets/social-sharing.liquid +185 -0
  69. package/test-theme/templates/account/dashboard.liquid +401 -0
  70. package/test-theme/templates/account/loyalty-redemption.liquid +405 -0
  71. package/test-theme/templates/account/loyalty.liquid +588 -0
  72. package/test-theme/templates/account/order-detail.liquid +230 -0
  73. package/test-theme/templates/account/orders.liquid +349 -0
  74. package/test-theme/templates/account/profile.liquid +758 -0
  75. package/test-theme/templates/account/register.liquid +232 -0
  76. package/test-theme/templates/account/return-orders.liquid +348 -0
  77. package/test-theme/templates/account/store-credit.liquid +464 -0
  78. package/test-theme/templates/account/subscriptions.liquid +601 -0
  79. package/test-theme/templates/account/wishlist.liquid +419 -0
  80. package/test-theme/templates/address-book.liquid +1092 -0
  81. package/test-theme/templates/categories.liquid +452 -0
  82. package/test-theme/templates/checkout.liquid +4511 -0
  83. package/test-theme/templates/error.liquid +384 -0
  84. package/test-theme/templates/index.liquid +11 -0
  85. package/test-theme/templates/login.liquid +185 -0
  86. package/test-theme/templates/order-confirmation.liquid +720 -0
  87. package/test-theme/templates/page.liquid +297 -0
  88. package/test-theme/templates/product-detail.liquid +4363 -0
  89. package/test-theme/templates/products.liquid +518 -0
  90. package/test-theme/templates/search.liquid +922 -0
  91. package/test-theme/theme.json.example +19 -0
  92. package/test-theme/widgets/brand-carousel.liquid +676 -0
  93. package/test-theme/widgets/brand.liquid +245 -0
  94. package/test-theme/widgets/carousel.liquid +843 -0
  95. package/test-theme/widgets/category-list-carousel.liquid +656 -0
  96. package/test-theme/widgets/category-list.liquid +340 -0
  97. package/test-theme/widgets/category.liquid +475 -0
  98. package/test-theme/widgets/discount-time.liquid +176 -0
  99. package/test-theme/widgets/footer-menu.liquid +695 -0
  100. package/test-theme/widgets/footer.liquid +179 -0
  101. package/test-theme/widgets/gallery.liquid +271 -0
  102. package/test-theme/widgets/header-menu.liquid +932 -0
  103. package/test-theme/widgets/header.liquid +159 -0
  104. package/test-theme/widgets/html.liquid +214 -0
  105. package/test-theme/widgets/news.liquid +217 -0
  106. package/test-theme/widgets/product-canvas.liquid +235 -0
  107. package/test-theme/widgets/product-carousel.liquid +502 -0
  108. package/test-theme/widgets/product.liquid +45 -0
  109. package/test-theme/widgets/recently-viewed.liquid +26 -0
  110. package/test-theme/widgets/shared/product-grid.liquid +339 -0
  111. package/test-theme/widgets/simple-product.liquid +42 -0
  112. package/test-theme/widgets/single-product.liquid +610 -0
  113. package/test-theme/widgets/spacebar-carousel.liquid +663 -0
  114. package/test-theme/widgets/spacebar.liquid +279 -0
  115. package/test-theme/widgets/splash.liquid +378 -0
  116. package/test-theme/widgets/testimonial-carousel.liquid +709 -0
@@ -0,0 +1,80 @@
1
+ /**
2
+ * File Watcher
3
+ * Watches theme files for changes and triggers reload
4
+ */
5
+
6
+ const chokidar = require('chokidar');
7
+ const path = require('path');
8
+
9
+ /**
10
+ * Setup file watcher for theme directory
11
+ * @param {string} themePath - Path to theme directory
12
+ * @param {Function} onChange - Callback when files change
13
+ * @returns {Object} Watcher instance
14
+ */
15
+ function setupFileWatcher(themePath, onChange) {
16
+ const watcher = chokidar.watch(themePath, {
17
+ ignored: [
18
+ /(^|[\/\\])\../, // Ignore dotfiles
19
+ '**/node_modules/**',
20
+ '**/.git/**',
21
+ '**/.o2vend-cache/**',
22
+ '**/*.log',
23
+ '**/.DS_Store'
24
+ ],
25
+ persistent: true,
26
+ ignoreInitial: true,
27
+ awaitWriteFinish: {
28
+ stabilityThreshold: 100,
29
+ pollInterval: 50
30
+ }
31
+ });
32
+
33
+ let changeTimeout = null;
34
+ const changedFiles = new Set();
35
+
36
+ watcher
37
+ .on('change', (filePath) => {
38
+ // Debounce multiple changes
39
+ changedFiles.add(filePath);
40
+
41
+ if (changeTimeout) {
42
+ clearTimeout(changeTimeout);
43
+ }
44
+
45
+ changeTimeout = setTimeout(() => {
46
+ const files = Array.from(changedFiles);
47
+ changedFiles.clear();
48
+
49
+ if (onChange) {
50
+ onChange(files);
51
+ }
52
+ }, 100);
53
+ })
54
+ .on('add', (filePath) => {
55
+ // New file added
56
+ changedFiles.add(filePath);
57
+
58
+ if (changeTimeout) {
59
+ clearTimeout(changeTimeout);
60
+ }
61
+
62
+ changeTimeout = setTimeout(() => {
63
+ const files = Array.from(changedFiles);
64
+ changedFiles.clear();
65
+
66
+ if (onChange) {
67
+ onChange(files);
68
+ }
69
+ }, 100);
70
+ })
71
+ .on('error', (error) => {
72
+ console.error('[FileWatcher] Error:', error);
73
+ });
74
+
75
+ return watcher;
76
+ }
77
+
78
+ module.exports = {
79
+ setupFileWatcher
80
+ };
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Hot Reload
3
+ * WebSocket server for live reloading in browser
4
+ */
5
+
6
+ const { Server } = require('socket.io');
7
+
8
+ /**
9
+ * Setup hot reload WebSocket server
10
+ * @returns {Server} Socket.IO server
11
+ */
12
+ function setupHotReload() {
13
+ const io = new Server({
14
+ path: '/socket.io',
15
+ serveClient: true,
16
+ cors: {
17
+ origin: '*',
18
+ methods: ['GET', 'POST']
19
+ }
20
+ });
21
+
22
+ // Handle connections (will be attached to HTTP server later)
23
+ io.on('connection', (socket) => {
24
+ // Client connected - will be used for hot reload
25
+ socket.on('disconnect', () => {
26
+ // Client disconnected
27
+ });
28
+ });
29
+
30
+ return io;
31
+ }
32
+
33
+ /**
34
+ * Inject hot reload script into HTML
35
+ * @param {string} html - HTML content
36
+ * @param {string} host - Server host
37
+ * @param {number} port - Server port
38
+ * @returns {string} HTML with hot reload script
39
+ */
40
+ function injectHotReloadScript(html, host = 'localhost', port = 3000) {
41
+ const script = `
42
+ <script src="/socket.io/socket.io.js"></script>
43
+ <script>
44
+ (function() {
45
+ if (typeof io !== 'undefined') {
46
+ const socket = io('http://${host}:${port}', {
47
+ path: '/socket.io',
48
+ transports: ['websocket', 'polling']
49
+ });
50
+
51
+ socket.on('connect', function() {
52
+ console.log('[Hot Reload] Connected');
53
+ });
54
+
55
+ socket.on('file-changed', function(files) {
56
+ console.log('[Hot Reload] Files changed:', files);
57
+
58
+ // Determine reload strategy based on file type
59
+ const hasCss = files.some(f => f.endsWith('.css'));
60
+ const hasLiquid = files.some(f => f.endsWith('.liquid'));
61
+ const hasJs = files.some(f => f.endsWith('.js'));
62
+
63
+ if (hasCss && !hasLiquid && !hasJs) {
64
+ // CSS only - inject without reload
65
+ console.log('[Hot Reload] Injecting CSS...');
66
+ files.filter(f => f.endsWith('.css')).forEach(function(file) {
67
+ const fileName = file.split(/[/\\\\]/).pop();
68
+ const links = document.querySelectorAll('link[rel="stylesheet"]');
69
+ links.forEach(function(link) {
70
+ if (link.href.includes(fileName)) {
71
+ const newLink = document.createElement('link');
72
+ newLink.rel = 'stylesheet';
73
+ newLink.href = link.href.split('?')[0] + '?v=' + Date.now();
74
+ link.parentNode.replaceChild(newLink, link);
75
+ }
76
+ });
77
+ });
78
+ } else {
79
+ // Full page reload
80
+ console.log('[Hot Reload] Reloading page...');
81
+ window.location.reload();
82
+ }
83
+ });
84
+
85
+ socket.on('disconnect', function() {
86
+ console.log('[Hot Reload] Disconnected');
87
+ });
88
+ }
89
+ })();
90
+ </script>
91
+ `;
92
+
93
+ // Inject before closing </body> tag
94
+ if (html.includes('</body>')) {
95
+ return html.replace('</body>', script + '</body>');
96
+ } else if (html.includes('</html>')) {
97
+ return html.replace('</html>', script + '</html>');
98
+ } else {
99
+ return html + script;
100
+ }
101
+ }
102
+
103
+ module.exports = {
104
+ setupHotReload,
105
+ injectHotReloadScript
106
+ };