domma-cms 0.1.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.
Files changed (135) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +469 -0
  3. package/admin/css/admin.css +1123 -0
  4. package/admin/index.html +72 -0
  5. package/admin/js/api.js +210 -0
  6. package/admin/js/app.js +270 -0
  7. package/admin/js/config/sidebar-config.js +107 -0
  8. package/admin/js/lib/card.js +63 -0
  9. package/admin/js/lib/image-editor.js +869 -0
  10. package/admin/js/lib/markdown-toolbar.js +421 -0
  11. package/admin/js/templates/dashboard.html +50 -0
  12. package/admin/js/templates/documentation.html +237 -0
  13. package/admin/js/templates/layouts.html +11 -0
  14. package/admin/js/templates/login.html +58 -0
  15. package/admin/js/templates/media.html +16 -0
  16. package/admin/js/templates/navigation.html +50 -0
  17. package/admin/js/templates/page-editor.html +126 -0
  18. package/admin/js/templates/pages.html +18 -0
  19. package/admin/js/templates/plugins.html +12 -0
  20. package/admin/js/templates/settings.html +190 -0
  21. package/admin/js/templates/tutorials.html +233 -0
  22. package/admin/js/templates/user-editor.html +12 -0
  23. package/admin/js/templates/users.html +10 -0
  24. package/admin/js/views/dashboard.js +48 -0
  25. package/admin/js/views/documentation.js +12 -0
  26. package/admin/js/views/index.js +33 -0
  27. package/admin/js/views/layouts.js +49 -0
  28. package/admin/js/views/login.js +254 -0
  29. package/admin/js/views/media.js +240 -0
  30. package/admin/js/views/navigation.js +152 -0
  31. package/admin/js/views/page-editor.js +479 -0
  32. package/admin/js/views/pages.js +64 -0
  33. package/admin/js/views/plugins.js +100 -0
  34. package/admin/js/views/settings.js +64 -0
  35. package/admin/js/views/tutorials.js +12 -0
  36. package/admin/js/views/user-editor.js +88 -0
  37. package/admin/js/views/users.js +73 -0
  38. package/bin/cli.js +334 -0
  39. package/config/auth.json +20 -0
  40. package/config/content.json +10 -0
  41. package/config/navigation.json +63 -0
  42. package/config/plugins.json +47 -0
  43. package/config/presets.json +34 -0
  44. package/config/server.json +6 -0
  45. package/config/site.json +33 -0
  46. package/package.json +67 -0
  47. package/plugins/back-to-top/admin/templates/back-to-top-settings.html +55 -0
  48. package/plugins/back-to-top/admin/views/back-to-top-settings.js +44 -0
  49. package/plugins/back-to-top/config.js +10 -0
  50. package/plugins/back-to-top/plugin.js +24 -0
  51. package/plugins/back-to-top/plugin.json +36 -0
  52. package/plugins/back-to-top/public/inject-body.html +105 -0
  53. package/plugins/cookie-consent/admin/templates/cookie-consent-settings.html +113 -0
  54. package/plugins/cookie-consent/admin/views/cookie-consent-settings.js +73 -0
  55. package/plugins/cookie-consent/config.js +30 -0
  56. package/plugins/cookie-consent/plugin.js +24 -0
  57. package/plugins/cookie-consent/plugin.json +36 -0
  58. package/plugins/cookie-consent/public/inject-body.html +69 -0
  59. package/plugins/custom-css/admin/templates/custom-css.html +17 -0
  60. package/plugins/custom-css/admin/views/custom-css.js +35 -0
  61. package/plugins/custom-css/config.js +1 -0
  62. package/plugins/custom-css/data/custom.css +0 -0
  63. package/plugins/custom-css/plugin.js +63 -0
  64. package/plugins/custom-css/plugin.json +32 -0
  65. package/plugins/custom-css/public/inject-head.html +1 -0
  66. package/plugins/domma-effects/admin/templates/domma-effects.html +488 -0
  67. package/plugins/domma-effects/admin/views/domma-effects.js +56 -0
  68. package/plugins/domma-effects/config.js +9 -0
  69. package/plugins/domma-effects/plugin.js +22 -0
  70. package/plugins/domma-effects/plugin.json +36 -0
  71. package/plugins/domma-effects/public/celebrations/core/canvas.js +111 -0
  72. package/plugins/domma-effects/public/celebrations/core/particles.js +144 -0
  73. package/plugins/domma-effects/public/celebrations/core/physics.js +166 -0
  74. package/plugins/domma-effects/public/celebrations/index.js +535 -0
  75. package/plugins/domma-effects/public/celebrations/themes/christmas.js +1805 -0
  76. package/plugins/domma-effects/public/celebrations/themes/guy-fawkes.js +1477 -0
  77. package/plugins/domma-effects/public/celebrations/themes/halloween.js +1837 -0
  78. package/plugins/domma-effects/public/celebrations/themes/st-andrews.js +1175 -0
  79. package/plugins/domma-effects/public/celebrations/themes/st-davids.js +1258 -0
  80. package/plugins/domma-effects/public/celebrations/themes/st-georges.js +1754 -0
  81. package/plugins/domma-effects/public/celebrations/themes/st-patricks.js +1290 -0
  82. package/plugins/domma-effects/public/celebrations/themes/valentines.js +1361 -0
  83. package/plugins/domma-effects/public/inject-body.html +268 -0
  84. package/plugins/example-analytics/admin/templates/analytics.html +10 -0
  85. package/plugins/example-analytics/admin/views/analytics.js +51 -0
  86. package/plugins/example-analytics/config.js +6 -0
  87. package/plugins/example-analytics/plugin.js +58 -0
  88. package/plugins/example-analytics/plugin.json +27 -0
  89. package/plugins/example-analytics/public/inject-body.html +13 -0
  90. package/plugins/example-analytics/public/inject-head.html +1 -0
  91. package/plugins/example-analytics/stats.json +1 -0
  92. package/plugins/form-builder/admin/templates/form-editor.html +158 -0
  93. package/plugins/form-builder/admin/templates/form-settings.html +29 -0
  94. package/plugins/form-builder/admin/templates/form-submissions.html +30 -0
  95. package/plugins/form-builder/admin/templates/forms-list.html +17 -0
  96. package/plugins/form-builder/admin/views/form-editor.js +817 -0
  97. package/plugins/form-builder/admin/views/form-settings.js +38 -0
  98. package/plugins/form-builder/admin/views/form-submissions.js +295 -0
  99. package/plugins/form-builder/admin/views/forms-list.js +164 -0
  100. package/plugins/form-builder/config.js +9 -0
  101. package/plugins/form-builder/data/forms/contact-details.json +63 -0
  102. package/plugins/form-builder/data/forms/contact.json +52 -0
  103. package/plugins/form-builder/data/submissions/contact-details.json +1 -0
  104. package/plugins/form-builder/data/submissions/contact.json +14 -0
  105. package/plugins/form-builder/email.js +103 -0
  106. package/plugins/form-builder/plugin.js +454 -0
  107. package/plugins/form-builder/plugin.json +56 -0
  108. package/plugins/form-builder/public/inject-body.html +270 -0
  109. package/plugins/form-builder/public/inject-head.html +42 -0
  110. package/public/css/site.css +189 -0
  111. package/public/js/site.js +109 -0
  112. package/scripts/copy-domma.js +48 -0
  113. package/scripts/fresh.js +41 -0
  114. package/scripts/reset.js +124 -0
  115. package/scripts/seed.js +666 -0
  116. package/scripts/setup.js +263 -0
  117. package/server/config.js +56 -0
  118. package/server/middleware/auth.js +97 -0
  119. package/server/routes/api/auth.js +116 -0
  120. package/server/routes/api/layouts.js +25 -0
  121. package/server/routes/api/media.js +93 -0
  122. package/server/routes/api/navigation.js +37 -0
  123. package/server/routes/api/pages.js +118 -0
  124. package/server/routes/api/plugins.js +46 -0
  125. package/server/routes/api/settings.js +25 -0
  126. package/server/routes/api/users.js +110 -0
  127. package/server/routes/public.js +108 -0
  128. package/server/server.js +169 -0
  129. package/server/services/content.js +298 -0
  130. package/server/services/images.js +334 -0
  131. package/server/services/markdown.js +297 -0
  132. package/server/services/plugins.js +246 -0
  133. package/server/services/renderer.js +80 -0
  134. package/server/services/users.js +212 -0
  135. package/server/templates/page.html +78 -0
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Canvas Management Utilities
3
+ * Handles canvas creation, resizing, and context management
4
+ */
5
+
6
+ export class CanvasManager {
7
+ constructor(options = {}) {
8
+ this.canvasId = options.canvasId || 'celebrations-canvas';
9
+ this.zIndex = options.zIndex || 999;
10
+ this.canvas = null;
11
+ this.ctx = null;
12
+ this.resizeTimeout = null;
13
+ this.resizeCallback = options.onResize || null;
14
+
15
+ // Bind methods
16
+ this._handleResize = this._handleResize.bind(this);
17
+ }
18
+
19
+ /**
20
+ * Create and append canvas to DOM
21
+ */
22
+ create() {
23
+ if (this.canvas) return; // Already created
24
+
25
+ this.canvas = document.createElement('canvas');
26
+ this.canvas.id = this.canvasId;
27
+ this.canvas.style.cssText = `
28
+ position: fixed;
29
+ top: 0;
30
+ left: 0;
31
+ width: 100vw;
32
+ height: 100vh;
33
+ pointer-events: none;
34
+ z-index: ${this.zIndex};
35
+ `;
36
+
37
+ this.ctx = this.canvas.getContext('2d', { alpha: true });
38
+ this.resize();
39
+ document.body.appendChild(this.canvas);
40
+
41
+ // Bind resize listener
42
+ window.addEventListener('resize', this._handleResize);
43
+ }
44
+
45
+ /**
46
+ * Resize canvas to match window dimensions
47
+ */
48
+ resize() {
49
+ if (!this.canvas) return;
50
+
51
+ this.canvas.width = window.innerWidth;
52
+ this.canvas.height = window.innerHeight;
53
+ }
54
+
55
+ /**
56
+ * Clear entire canvas
57
+ */
58
+ clear() {
59
+ if (!this.ctx) return;
60
+ this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
61
+ }
62
+
63
+ /**
64
+ * Get canvas dimensions
65
+ */
66
+ getDimensions() {
67
+ return {
68
+ width: this.canvas?.width || 0,
69
+ height: this.canvas?.height || 0
70
+ };
71
+ }
72
+
73
+ /**
74
+ * Check if mobile device
75
+ */
76
+ isMobile() {
77
+ return window.innerWidth < 768;
78
+ }
79
+
80
+ /**
81
+ * Remove canvas from DOM and cleanup
82
+ */
83
+ destroy() {
84
+ window.removeEventListener('resize', this._handleResize);
85
+
86
+ if (this.canvas && this.canvas.parentNode) {
87
+ this.canvas.parentNode.removeChild(this.canvas);
88
+ }
89
+
90
+ this.canvas = null;
91
+ this.ctx = null;
92
+ }
93
+
94
+ /**
95
+ * Handle window resize with debouncing
96
+ * @private
97
+ */
98
+ _handleResize() {
99
+ if (this.resizeTimeout) {
100
+ clearTimeout(this.resizeTimeout);
101
+ }
102
+
103
+ this.resizeTimeout = setTimeout(() => {
104
+ this.resize();
105
+
106
+ if (this.resizeCallback) {
107
+ this.resizeCallback();
108
+ }
109
+ }, 250);
110
+ }
111
+ }
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Particle System Base
3
+ * Handles particle creation, depth layers, and lifecycle management
4
+ */
5
+
6
+ /**
7
+ * Create a base particle with depth layering
8
+ * @param {Object} config - Configuration for particle creation
9
+ * @param {number} canvasWidth - Canvas width for positioning
10
+ * @param {number} canvasHeight - Canvas height for positioning
11
+ * @returns {Object} Particle object
12
+ */
13
+ export function createParticle(config, canvasWidth, canvasHeight) {
14
+ // Determine depth layer (front, middle, back)
15
+ const depth = Math.random();
16
+ let size, speed, opacity, windSpeed;
17
+
18
+ if (depth < 0.33) {
19
+ // Front layer - larger, faster, more opaque
20
+ size = config.sizeRange[0] + Math.random() * (config.sizeRange[1] - config.sizeRange[0]) * 1.5;
21
+ speed = config.speedRange[0] + Math.random() * (config.speedRange[1] - config.speedRange[0]) * 1.3;
22
+ opacity = 0.8 + Math.random() * 0.2;
23
+ windSpeed = 0.01 + Math.random() * 0.02;
24
+ } else if (depth < 0.66) {
25
+ // Middle layer
26
+ size = config.sizeRange[0] + Math.random() * (config.sizeRange[1] - config.sizeRange[0]);
27
+ speed = config.speedRange[0] + Math.random() * (config.speedRange[1] - config.speedRange[0]);
28
+ opacity = 0.5 + Math.random() * 0.2;
29
+ windSpeed = 0.02 + Math.random() * 0.03;
30
+ } else {
31
+ // Back layer - smaller, slower, less opaque
32
+ size = config.sizeRange[0] + Math.random() * (config.sizeRange[1] - config.sizeRange[0]) * 0.7;
33
+ speed = config.speedRange[0] + Math.random() * (config.speedRange[1] - config.speedRange[0]) * 0.7;
34
+ opacity = 0.3 + Math.random() * 0.2;
35
+ windSpeed = 0.03 + Math.random() * 0.04;
36
+ }
37
+
38
+ return {
39
+ x: Math.random() * canvasWidth,
40
+ y: Math.random() * canvasHeight - canvasHeight, // Start above viewport
41
+ size: size,
42
+ speed: speed,
43
+ opacity: opacity,
44
+ windOffset: Math.random() * Math.PI * 2,
45
+ windSpeed: windSpeed,
46
+ rotation: Math.random() * Math.PI * 2,
47
+ rotationSpeed: (Math.random() - 0.5) * 0.02,
48
+ depth: depth
49
+ };
50
+ }
51
+
52
+ /**
53
+ * Create a static decoration (tree, house, etc.)
54
+ * @param {string} type - Type of decoration
55
+ * @param {number} canvasWidth - Canvas width for positioning
56
+ * @param {number} canvasHeight - Canvas height for positioning
57
+ * @param {Object} options - Additional options
58
+ * @returns {Object} Static particle object
59
+ */
60
+ export function createStaticDecoration(type, canvasWidth, canvasHeight, options = {}) {
61
+ return {
62
+ type: type,
63
+ x: options.x !== undefined ? options.x : Math.random() * canvasWidth,
64
+ y: options.y !== undefined ? options.y : Math.random() * canvasHeight,
65
+ vx: 0,
66
+ vy: 0,
67
+ size: options.size || (20 + Math.random() * 15),
68
+ opacity: options.opacity || (0.6 + Math.random() * 0.3),
69
+ rotation: options.rotation || 0,
70
+ rotationSpeed: 0,
71
+ active: true,
72
+ static: true,
73
+ ...options
74
+ };
75
+ }
76
+
77
+ /**
78
+ * Create a moving special particle (sleigh, bird, etc.)
79
+ * @param {string} type - Type of special particle
80
+ * @param {number} canvasWidth - Canvas width for positioning
81
+ * @param {number} canvasHeight - Canvas height for positioning
82
+ * @param {Object} options - Movement and appearance options
83
+ * @returns {Object} Moving particle object
84
+ */
85
+ export function createMovingParticle(type, canvasWidth, canvasHeight, options = {}) {
86
+ const startX = options.startX !== undefined ? options.startX : -100;
87
+ const startY = options.startY !== undefined ? options.startY : canvasHeight * 0.3;
88
+
89
+ return {
90
+ type: type,
91
+ x: startX,
92
+ y: startY,
93
+ vx: options.vx || 1.5,
94
+ vy: options.vy || 0,
95
+ size: options.size || 40,
96
+ opacity: options.opacity || 1,
97
+ rotation: options.rotation || 0,
98
+ rotationSpeed: options.rotationSpeed || 0,
99
+ active: true,
100
+ static: false,
101
+ // Sine wave motion
102
+ waveAmplitude: options.waveAmplitude || 0,
103
+ waveFrequency: options.waveFrequency || 0,
104
+ waveOffset: options.waveOffset || 0,
105
+ ...options
106
+ };
107
+ }
108
+
109
+ /**
110
+ * Recycle particle to top/side of canvas
111
+ * @param {Object} particle - Particle to recycle
112
+ * @param {number} canvasWidth - Canvas width
113
+ * @param {number} canvasHeight - Canvas height
114
+ */
115
+ export function recycleParticle(particle, canvasWidth, canvasHeight) {
116
+ if (particle.y > canvasHeight + 10) {
117
+ particle.y = -10;
118
+ particle.x = Math.random() * canvasWidth;
119
+ }
120
+
121
+ // Wrap horizontally
122
+ if (particle.x < -10) {
123
+ particle.x = canvasWidth + 10;
124
+ } else if (particle.x > canvasWidth + 10) {
125
+ particle.x = -10;
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Check if particle is off-screen and should be removed
131
+ * @param {Object} particle - Particle to check
132
+ * @param {number} canvasWidth - Canvas width
133
+ * @param {number} canvasHeight - Canvas height
134
+ * @param {number} buffer - Extra buffer space (default 100)
135
+ * @returns {boolean} True if particle is off-screen
136
+ */
137
+ export function isOffScreen(particle, canvasWidth, canvasHeight, buffer = 100) {
138
+ return (
139
+ particle.x < -buffer ||
140
+ particle.x > canvasWidth + buffer ||
141
+ particle.y < -buffer ||
142
+ particle.y > canvasHeight + buffer
143
+ );
144
+ }
@@ -0,0 +1,166 @@
1
+ /**
2
+ * Physics Utilities
3
+ * Handles wind, gravity, movement, and physics simulation
4
+ */
5
+
6
+ export class PhysicsEngine {
7
+ constructor(options = {}) {
8
+ this.windGust = 0; // Current wind strength
9
+ this.windGustTarget = 0; // Target wind strength
10
+ this.lastGustTime = 0;
11
+ this.gustInterval = options.gustInterval || [5000, 15000]; // Min/max ms between gusts
12
+ this.gustStrength = options.gustStrength || [-2, 2]; // Min/max wind force
13
+ }
14
+
15
+ /**
16
+ * Update wind physics
17
+ * @param {number} currentTime - Current timestamp
18
+ */
19
+ updateWind(currentTime) {
20
+ // Generate new wind gust periodically
21
+ const [minInterval, maxInterval] = this.gustInterval;
22
+ if (currentTime - this.lastGustTime > minInterval + Math.random() * (maxInterval - minInterval)) {
23
+ const [minStrength, maxStrength] = this.gustStrength;
24
+ this.windGustTarget = minStrength + Math.random() * (maxStrength - minStrength);
25
+ this.lastGustTime = currentTime;
26
+ }
27
+
28
+ // Smooth wind transition
29
+ this.windGust += (this.windGustTarget - this.windGust) * 0.02;
30
+ }
31
+
32
+ /**
33
+ * Get current wind force
34
+ * @returns {number} Current wind force
35
+ */
36
+ getWindForce() {
37
+ return this.windGust;
38
+ }
39
+
40
+ /**
41
+ * Reset wind to calm
42
+ */
43
+ resetWind() {
44
+ this.windGust = 0;
45
+ this.windGustTarget = 0;
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Update particle position with gravity and wind
51
+ * @param {Object} particle - Particle to update
52
+ * @param {number} deltaTime - Time since last frame
53
+ * @param {number} windForce - Current wind force
54
+ */
55
+ export function updateParticlePhysics(particle, deltaTime, windForce = 0) {
56
+ const normalizedDelta = deltaTime / (1000 / 60); // Normalize to 60fps
57
+
58
+ // Apply gravity (downward movement) - support both speed and vy
59
+ const verticalSpeed = particle.vy || particle.speed || 0;
60
+ particle.y += verticalSpeed * normalizedDelta;
61
+
62
+ // Apply horizontal velocity if present
63
+ if (particle.vx) {
64
+ particle.x += particle.vx * normalizedDelta;
65
+ }
66
+
67
+ // Apply wind drift + wind gust
68
+ if (particle.windOffset !== undefined && particle.windSpeed !== undefined) {
69
+ particle.windOffset += particle.windSpeed * normalizedDelta;
70
+ const baseWind = Math.sin(particle.windOffset) * 0.5;
71
+ particle.x += (baseWind + windForce) * normalizedDelta;
72
+ }
73
+
74
+ // Apply rotation
75
+ if (particle.rotationSpeed) {
76
+ particle.rotation += particle.rotationSpeed * normalizedDelta;
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Update moving particle with sine wave motion
82
+ * @param {Object} particle - Moving particle to update
83
+ * @param {number} deltaTime - Time since last frame
84
+ * @param {number} currentTime - Current timestamp
85
+ */
86
+ export function updateMovingParticle(particle, deltaTime, currentTime) {
87
+ const normalizedDelta = deltaTime / (1000 / 60);
88
+
89
+ // Update horizontal position
90
+ particle.x += particle.vx * normalizedDelta;
91
+
92
+ // Apply sine wave vertical motion if configured
93
+ if (particle.waveAmplitude && particle.waveFrequency) {
94
+ const waveProgress = (currentTime * particle.waveFrequency) / 1000;
95
+ particle.y = particle.baseY + Math.sin(waveProgress + particle.waveOffset) * particle.waveAmplitude;
96
+ } else {
97
+ particle.y += particle.vy * normalizedDelta;
98
+ }
99
+
100
+ // Apply rotation
101
+ if (particle.rotationSpeed) {
102
+ particle.rotation += particle.rotationSpeed * normalizedDelta;
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Apply gravity to particle
108
+ * @param {Object} particle - Particle to affect
109
+ * @param {number} deltaTime - Time since last frame
110
+ * @param {number} gravity - Gravity force (default 0.5)
111
+ */
112
+ export function applyGravity(particle, deltaTime, gravity = 0.5) {
113
+ const normalizedDelta = deltaTime / (1000 / 60);
114
+ particle.vy += gravity * normalizedDelta;
115
+ particle.y += particle.vy * normalizedDelta;
116
+ }
117
+
118
+ /**
119
+ * Apply bounce physics when particle hits ground
120
+ * @param {Object} particle - Particle to bounce
121
+ * @param {number} groundY - Y position of ground
122
+ * @param {number} restitution - Bounce factor (0-1, default 0.6)
123
+ */
124
+ export function applyBounce(particle, groundY, restitution = 0.6) {
125
+ if (particle.y >= groundY && particle.vy > 0) {
126
+ particle.y = groundY;
127
+ particle.vy *= -restitution;
128
+
129
+ // Stop bouncing if velocity is too low
130
+ if (Math.abs(particle.vy) < 0.5) {
131
+ particle.vy = 0;
132
+ }
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Calculate normalized delta time for consistent animation
138
+ * @param {number} deltaTime - Time since last frame in ms
139
+ * @param {number} targetFPS - Target framerate (default 60)
140
+ * @returns {number} Normalized delta
141
+ */
142
+ export function normalizeDelta(deltaTime, targetFPS = 60) {
143
+ return deltaTime / (1000 / targetFPS);
144
+ }
145
+
146
+ /**
147
+ * Interpolate between two values
148
+ * @param {number} start - Start value
149
+ * @param {number} end - End value
150
+ * @param {number} t - Interpolation factor (0-1)
151
+ * @returns {number} Interpolated value
152
+ */
153
+ export function lerp(start, end, t) {
154
+ return start + (end - start) * t;
155
+ }
156
+
157
+ /**
158
+ * Clamp value between min and max
159
+ * @param {number} value - Value to clamp
160
+ * @param {number} min - Minimum value
161
+ * @param {number} max - Maximum value
162
+ * @returns {number} Clamped value
163
+ */
164
+ export function clamp(value, min, max) {
165
+ return Math.min(Math.max(value, min), max);
166
+ }