mount-observer 0.1.23 → 0.1.24

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/Synthesizer.js CHANGED
@@ -101,6 +101,44 @@ export class Synthesizer extends HTMLElement {
101
101
  }
102
102
  }
103
103
  }
104
+ /**
105
+ * Check if a script element should be processed based on include/exclude attributes.
106
+ *
107
+ * Rules:
108
+ * - If passthrough attribute exists, return false (don't process any scripts)
109
+ * - If include or exclude attributes exist and script has no id, return false (security)
110
+ * - If include attribute exists, only process scripts with IDs in the include list
111
+ * - If exclude attribute exists, don't process scripts with IDs in the exclude list
112
+ * - Otherwise, return true (process the script)
113
+ *
114
+ * Made protected so subscribers can check if syndicator would allow a script.
115
+ */
116
+ checkIfAllowed(scriptElement) {
117
+ // Passthrough mode - don't process any scripts
118
+ if (this.hasAttribute('passthrough')) {
119
+ return false;
120
+ }
121
+ const scriptId = scriptElement.getAttribute('id');
122
+ // Security: If include or exclude attributes exist, script must have an ID
123
+ if ((this.hasAttribute('include') || this.hasAttribute('exclude')) && !scriptId) {
124
+ return false;
125
+ }
126
+ // Include list - only process scripts with IDs in the list
127
+ if (this.hasAttribute('include')) {
128
+ const includeList = this.getAttribute('include').split(' ').filter(s => s.trim());
129
+ if (!includeList.includes(scriptId)) {
130
+ return false;
131
+ }
132
+ }
133
+ // Exclude list - don't process scripts with IDs in the list
134
+ if (this.hasAttribute('exclude')) {
135
+ const excludeList = this.getAttribute('exclude').split(' ').filter(s => s.trim());
136
+ if (excludeList.includes(scriptId)) {
137
+ return false;
138
+ }
139
+ }
140
+ return true;
141
+ }
104
142
  /**
105
143
  * Initialize as syndicator (in document root).
106
144
  * Watches for script elements and broadcasts them to subscribers.
@@ -109,7 +147,9 @@ export class Synthesizer extends HTMLElement {
109
147
  // Process existing script elements
110
148
  const scripts = this.querySelectorAll('script[type="mountobserver"], script[type="emc"]');
111
149
  scripts.forEach(script => {
112
- this.#broadcastScript(script);
150
+ if (this.checkIfAllowed(script)) {
151
+ this.#broadcastScript(script);
152
+ }
113
153
  });
114
154
  // Watch for new script elements
115
155
  this.#mutationObserver = new MutationObserver((mutations) => {
@@ -118,7 +158,9 @@ export class Synthesizer extends HTMLElement {
118
158
  if (node instanceof HTMLScriptElement) {
119
159
  const type = node.getAttribute('type');
120
160
  if (type === 'mountobserver' || type === 'emc') {
121
- this.#broadcastScript(node);
161
+ if (this.checkIfAllowed(node)) {
162
+ this.#broadcastScript(node);
163
+ }
122
164
  }
123
165
  }
124
166
  }
@@ -147,9 +189,12 @@ export class Synthesizer extends HTMLElement {
147
189
  return;
148
190
  }
149
191
  // Process existing scripts from syndicator
192
+ // Only process scripts that pass the syndicator's filtering
150
193
  const scripts = syndicator.querySelectorAll('script[type="mountobserver"], script[type="emc"]');
151
194
  scripts.forEach(script => {
152
- this.#processScript(script);
195
+ if (syndicator.checkIfAllowed(script)) {
196
+ this.#processScript(script);
197
+ }
153
198
  });
154
199
  // Subscribe to new scripts
155
200
  syndicator.addEventListener(AddedScriptElementEvent.eventName, (e) => {
package/Synthesizer.ts CHANGED
@@ -114,6 +114,50 @@ export abstract class Synthesizer extends HTMLElement {
114
114
  }
115
115
  }
116
116
 
117
+ /**
118
+ * Check if a script element should be processed based on include/exclude attributes.
119
+ *
120
+ * Rules:
121
+ * - If passthrough attribute exists, return false (don't process any scripts)
122
+ * - If include or exclude attributes exist and script has no id, return false (security)
123
+ * - If include attribute exists, only process scripts with IDs in the include list
124
+ * - If exclude attribute exists, don't process scripts with IDs in the exclude list
125
+ * - Otherwise, return true (process the script)
126
+ *
127
+ * Made protected so subscribers can check if syndicator would allow a script.
128
+ */
129
+ protected checkIfAllowed(scriptElement: HTMLScriptElement): boolean {
130
+ // Passthrough mode - don't process any scripts
131
+ if (this.hasAttribute('passthrough')) {
132
+ return false;
133
+ }
134
+
135
+ const scriptId = scriptElement.getAttribute('id');
136
+
137
+ // Security: If include or exclude attributes exist, script must have an ID
138
+ if ((this.hasAttribute('include') || this.hasAttribute('exclude')) && !scriptId) {
139
+ return false;
140
+ }
141
+
142
+ // Include list - only process scripts with IDs in the list
143
+ if (this.hasAttribute('include')) {
144
+ const includeList = this.getAttribute('include')!.split(' ').filter(s => s.trim());
145
+ if (!includeList.includes(scriptId!)) {
146
+ return false;
147
+ }
148
+ }
149
+
150
+ // Exclude list - don't process scripts with IDs in the list
151
+ if (this.hasAttribute('exclude')) {
152
+ const excludeList = this.getAttribute('exclude')!.split(' ').filter(s => s.trim());
153
+ if (excludeList.includes(scriptId!)) {
154
+ return false;
155
+ }
156
+ }
157
+
158
+ return true;
159
+ }
160
+
117
161
  /**
118
162
  * Initialize as syndicator (in document root).
119
163
  * Watches for script elements and broadcasts them to subscribers.
@@ -122,7 +166,9 @@ export abstract class Synthesizer extends HTMLElement {
122
166
  // Process existing script elements
123
167
  const scripts = this.querySelectorAll('script[type="mountobserver"], script[type="emc"]');
124
168
  scripts.forEach(script => {
125
- this.#broadcastScript(script as HTMLScriptElement);
169
+ if (this.checkIfAllowed(script as HTMLScriptElement)) {
170
+ this.#broadcastScript(script as HTMLScriptElement);
171
+ }
126
172
  });
127
173
 
128
174
  // Watch for new script elements
@@ -132,7 +178,9 @@ export abstract class Synthesizer extends HTMLElement {
132
178
  if (node instanceof HTMLScriptElement) {
133
179
  const type = node.getAttribute('type');
134
180
  if (type === 'mountobserver' || type === 'emc') {
135
- this.#broadcastScript(node);
181
+ if (this.checkIfAllowed(node)) {
182
+ this.#broadcastScript(node);
183
+ }
136
184
  }
137
185
  }
138
186
  }
@@ -166,9 +214,12 @@ export abstract class Synthesizer extends HTMLElement {
166
214
  }
167
215
 
168
216
  // Process existing scripts from syndicator
217
+ // Only process scripts that pass the syndicator's filtering
169
218
  const scripts = syndicator.querySelectorAll('script[type="mountobserver"], script[type="emc"]');
170
219
  scripts.forEach(script => {
171
- this.#processScript(script as HTMLScriptElement);
220
+ if (syndicator.checkIfAllowed(script as HTMLScriptElement)) {
221
+ this.#processScript(script as HTMLScriptElement);
222
+ }
172
223
  });
173
224
 
174
225
  // Subscribe to new scripts
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "mount-observer",
3
- "version": "0.1.23",
3
+ "version": "0.1.24",
4
4
  "description": "Observe and act on css matches.",
5
5
  "main": "MountObserver.js",
6
6
  "module": "MountObserver.js",
7
7
  "dependencies": {
8
- "assign-gingerly": "0.0.23",
8
+ "assign-gingerly": "0.0.24",
9
9
  "id-generation": "0.0.4"
10
10
  },
11
11
  "devDependencies": {