Skip to content

Commit

Permalink
Patch - Core: Ensure wb.getId() always returns unique IDs (wet-boew#9776
Browse files Browse the repository at this point in the history
)

WET core's getId() method was initially designed to increment a seed number in conjunction with a WET-specific auto ID naming scheme ("wb-auto-#").

That's fine in theory, but doesn't guarantee that it'll return a unique ID. It can clash with hardcoded IDs that use the same naming scheme - such as pages whose authors mistakenly-hardcode "post-JS" HTML markup generated by plugins.

For example, if a "botched" plugin implementation contains a hardcoded "wb-auto-5" ID... wb.getId() might independently generate the same ID and return it to a "good" plugin somewhere else in the page. End result is that the "good" plugin will insert a duplicate ID into the page and possibly even break.

This resolves the potential for clashes by revising getId() to:
* Check for conflicting hardcoded IDs the first time it's called
* Increment its initial seed number if needed (to surpass the highest conflicting ID's number)
* Show console errors for any hardcoded IDs starting with WET's auto ID prefix (wb-auto-)

Also adds a WET core working examples page to demonstrate an ID conflict scenario in action.

Thanks to @fsnoddy for initially spotting this and providing insight.
  • Loading branch information
EricDunsworth authored Jul 3, 2024
1 parent 020057d commit f81edda
Show file tree
Hide file tree
Showing 5 changed files with 280 additions and 3 deletions.
10 changes: 9 additions & 1 deletion site/pages/docs/ref/core/core-en.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"categoryfile": "other",
"description": "Core WET object.",
"altLangPrefix": "core",
"dateModified": "2023-03-28"
"dateModified": "2024-07-02"
}
---
<div class="wb-prettify all-pre hide"></div>
Expand All @@ -21,6 +21,14 @@
<p>Core WET object.</p>
</section>

<section>
<h2>Working example</h2>
<ul>
<li><a href="../../../demos/core/core-en.html">English examples</a></li>
<li><a href="../../../demos/core/core-fr.html">French examples</a></li>
</ul>
</section>

<section>
<h2>Language (<code>wb.lang</code>)</h2>
<p>WET's language is derived from the <code>html</code> element's <code>lang</code> attribute. A formatted version of the page's language code is stored in the <code>wb.lang</code> variable.</p>
Expand Down
10 changes: 9 additions & 1 deletion site/pages/docs/ref/core/core-fr.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"categoryfile": "other",
"description": "Objet principal de la BOEW.",
"altLangPrefix": "core",
"dateModified": "2023-03-28"
"dateModified": "2024-07-02"
}
---
<div class="wb-prettify all-pre hide"></div>
Expand All @@ -23,6 +23,14 @@
<p>Objet principal de la BOEW.</p>
</section>

<section>
<h2>Exemples</h2>
<ul>
<li><a href="../../../demos/core/core-en.html">Exemples anglais</a></li>
<li><a href="../../../demos/core/core-fr.html">Exemples français</a></li>
</ul>
</section>

<div lang="en">
<section>
<h2>Language (<code>wb.lang</code>)</h2>
Expand Down
27 changes: 26 additions & 1 deletion src/core/wb.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,32 @@ var getUrlParts = function( url ) {
},

getId: function() {
return "wb-auto-" + ( seed += 1 );
var idPrefix = "wb-auto-",
ids,
numberCandidate,
numbers = [];

// Check for conflicting hardcoded IDs the first time an ID is requested
if ( !seed ) {
ids = document.querySelectorAll( "[id^='" + idPrefix + "']" );

// Loop through elements whose IDs begin with the prefix
ids.forEach( function( currentElm ) {
numberCandidate = currentElm.id.substring( idPrefix.length );

// Verify whether the ID ends with a conflicting number and add it to an array
if ( numberCandidate.search( /^\d+$/ ) !== -1 ) {
numbers.push( numberCandidate );
}

console.error( "wb.getId: ID '" + currentElm.id + "' isn't supposed to be hardcoded in the page. Please remove it or change its prefix to something different than '" + idPrefix + "'." );
} );

// Set the seed to the array's highest number (will be incremented later)
seed = numbers.length ? Math.max.apply( null, numbers ) : seed;
}

return idPrefix + ( seed += 1 );
},

init: function( event, componentName, selector, noAutoId ) {
Expand Down
118 changes: 118 additions & 0 deletions src/other/core/core-en.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
---
{
"title": "WET core",
"language": "en",
"category": "Other",
"description": "Working examples of WET core's built-in methods.",
"tag": "core",
"parentdir": "core",
"altLangPrefix": "core",
"dateModified": "2024-07-02"
}
---

<div class="wb-prettify all-pre hide"></div>

<p>{{description}}</p>

<nav>
<h2>On this page</h2>
<ul>
<li><a href="#ex1">Example 1 - <code>wb.getId()</code> and ID conflicts</a></li>
</ul>
</nav>

<section>
<h2 id="ex1">Example 1 - <code>wb.getId()</code> and ID conflicts</h2>
<p>Demonstrates how <code>wb.getId()</code> reacts when hardcoded IDs conflict with its naming convention (anything starting with <code>wb-auto-</code>).</p>

<section>
<h3>Hardcoded IDs</h3>
<ul>
<li id="wb-auto-"><code>wb-auto-</code></li>
<li id="wb-auto-3abc"><code>wb-auto-3abc</code></li>
<li id="wb-auto-4."><code>wb-auto-4.</code></li>
<li id="wb-auto-17"><code>wb-auto-17</code></li>
<li id="wb-auto-5.0"><code>wb-auto-5.0</code></li>
<li id="wb-auto-1"><code>wb-auto-1</code></li>
<li id="wb-auto-6.1"><code>wb-auto-6.1</code></li>
<li id="wb-auto-2"><code>wb-auto-2</code></li>
<li id="wb-auto-abc9"><code>wb-auto-abc9</code></li>
</ul>
</section>

<section>
<h3>Tables plugin</h3>
<p>This plugin calls <code>wb.getId()</code>.</p>
<table class="wb-tables table">
<thead>
<tr>
<th>Rendering engine</th>
<th>Browser</th>
</tr>
</thead>
<tbody>
<tr>
<td>Blink</td>
<td>Chromium</td>
</tr>
<tr>
<td>Gecko</td>
<td>Firefox</td>
</tr>
<tr>
<td>WebKit</td>
<td>Safari</td>
</tr>
</tbody>
</table>
</section>

<h3>Code sample</h3>
<pre><code>&lt;section&gt;
&lt;h2 id="ex1"&gt;Example 1 - &lt;code&gt;wb.getId()&lt;/code&gt; and ID conflicts&lt;/h2&gt;
&lt;p&gt;Demonstrates how &lt;code&gt;wb.getId()&lt;/code&gt; reacts when hardcoded IDs conflict with its naming convention (anything starting with &lt;code&gt;wb-auto-&lt;/code&gt;).&lt;/p&gt;

&lt;section&gt;
&lt;h3&gt;Hardcoded IDs&lt;/h3&gt;
&lt;ul&gt;
&lt;li id="wb-auto-"&gt;&lt;code&gt;wb-auto-&lt;/code&gt;&lt;/li&gt;
&lt;li id="wb-auto-3abc"&gt;&lt;code&gt;wb-auto-3abc&lt;/code&gt;&lt;/li&gt;
&lt;li id="wb-auto-4."&gt;&lt;code&gt;wb-auto-4.&lt;/code&gt;&lt;/li&gt;
&lt;li id="wb-auto-17"&gt;&lt;code&gt;wb-auto-17&lt;/code&gt;&lt;/li&gt;
&lt;li id="wb-auto-5.0"&gt;&lt;code&gt;wb-auto-5.0&lt;/code&gt;&lt;/li&gt;
&lt;li id="wb-auto-1"&gt;&lt;code&gt;wb-auto-1&lt;/code&gt;&lt;/li&gt;
&lt;li id="wb-auto-6.1"&gt;&lt;code&gt;wb-auto-6.1&lt;/code&gt;&lt;/li&gt;
&lt;li id="wb-auto-2"&gt;&lt;code&gt;wb-auto-2&lt;/code&gt;&lt;/li&gt;
&lt;li id="wb-auto-abc9"&gt;&lt;code&gt;wb-auto-abc9&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;

&lt;section&gt;
&lt;h3&gt;Tables plugin&lt;/h3&gt;
&lt;p&gt;This plugin calls &lt;code&gt;wb.getId()&lt;/code&gt;.&lt;/p&gt;
&lt;table class="wb-tables table"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rendering engine&lt;/th&gt;
&lt;th&gt;Browser&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Blink&lt;/td&gt;
&lt;td&gt;Chromium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gecko&lt;/td&gt;
&lt;td&gt;Firefox&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WebKit&lt;/td&gt;
&lt;td&gt;Safari&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
&lt;/section&gt;</code></pre>
</section>
118 changes: 118 additions & 0 deletions src/other/core/core-fr.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
---
{
"title": "Base de la BOEW",
"language": "en",
"category": "Other",
"description": "Exemples pratiques des méthodes natifs de la base de la BOEW.",
"tag": "core",
"parentdir": "core",
"altLangPrefix": "core",
"dateModified": "2024-07-02"
}
---

<div class="wb-prettify all-pre hide"></div>

<p>{{description}}</p>

<nav>
<h2>Sur cette page</h2>
<ul>
<li><a href="#ex1">Exemple 1 - <code>wb.getId()</code> et conflits d’IDs</a></li>
</ul>
</nav>

<section>
<h2 id="ex1">Exemple 1 - <code>wb.getId()</code> et conflits d’IDs</h2>
<p>Démontre comment <code>wb.getId()</code> réagit quand des IDs codés en dur entrent en conflit avec sa convention de nommage (tout ce qui commence par <code>wb-auto-</code>).</p>

<section>
<h3>IDs codés en dur</h3>
<ul>
<li id="wb-auto-"><code>wb-auto-</code></li>
<li id="wb-auto-3abc"><code>wb-auto-3abc</code></li>
<li id="wb-auto-4."><code>wb-auto-4.</code></li>
<li id="wb-auto-17"><code>wb-auto-17</code></li>
<li id="wb-auto-5.0"><code>wb-auto-5.0</code></li>
<li id="wb-auto-1"><code>wb-auto-1</code></li>
<li id="wb-auto-6.1"><code>wb-auto-6.1</code></li>
<li id="wb-auto-2"><code>wb-auto-2</code></li>
<li id="wb-auto-abc9"><code>wb-auto-abc9</code></li>
</ul>
</section>

<section>
<h3>Plugiciel de tableaux</h3>
<p>This plugin calls <code>wb.getId()</code>.</p>
<table class="wb-tables table">
<thead>
<tr>
<th>Moteur de rendu</th>
<th>Navigateur</th>
</tr>
</thead>
<tbody>
<tr>
<td>Blink</td>
<td>Chromium</td>
</tr>
<tr>
<td>Gecko</td>
<td>Firefox</td>
</tr>
<tr>
<td>WebKit</td>
<td>Safari</td>
</tr>
</tbody>
</table>
</section>

<h3>Exemple de code</h3>
<pre><code>&lt;section&gt;
&lt;h2 id="ex1"&gt;Exemple 1 - &lt;code&gt;wb.getId()&lt;/code&gt; et conflits d’IDs&lt;/h2&gt;
&lt;p&gt;Démontre comment &lt;code&gt;wb.getId()&lt;/code&gt; réagit quand des IDs codés en dur entrent en conflit avec sa convention de nommage (tout ce qui commence par &lt;code&gt;wb-auto-&lt;/code&gt;).&lt;/p&gt;

&lt;section&gt;
&lt;h3&gt;IDs codés en dur&lt;/h3&gt;
&lt;ul&gt;
&lt;li id="wb-auto-"&gt;&lt;code&gt;wb-auto-&lt;/code&gt;&lt;/li&gt;
&lt;li id="wb-auto-3abc"&gt;&lt;code&gt;wb-auto-3abc&lt;/code&gt;&lt;/li&gt;
&lt;li id="wb-auto-4."&gt;&lt;code&gt;wb-auto-4.&lt;/code&gt;&lt;/li&gt;
&lt;li id="wb-auto-17"&gt;&lt;code&gt;wb-auto-17&lt;/code&gt;&lt;/li&gt;
&lt;li id="wb-auto-5.0"&gt;&lt;code&gt;wb-auto-5.0&lt;/code&gt;&lt;/li&gt;
&lt;li id="wb-auto-1"&gt;&lt;code&gt;wb-auto-1&lt;/code&gt;&lt;/li&gt;
&lt;li id="wb-auto-6.1"&gt;&lt;code&gt;wb-auto-6.1&lt;/code&gt;&lt;/li&gt;
&lt;li id="wb-auto-2"&gt;&lt;code&gt;wb-auto-2&lt;/code&gt;&lt;/li&gt;
&lt;li id="wb-auto-abc9"&gt;&lt;code&gt;wb-auto-abc9&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt;

&lt;section&gt;
&lt;h3&gt;Plugiciel de tableaux&lt;/h3&gt;
&lt;p&gt;This plugin calls &lt;code&gt;wb.getId()&lt;/code&gt;.&lt;/p&gt;
&lt;table class="wb-tables table"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Moteur de rendu&lt;/th&gt;
&lt;th&gt;Navigateur&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Blink&lt;/td&gt;
&lt;td&gt;Chromium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gecko&lt;/td&gt;
&lt;td&gt;Firefox&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WebKit&lt;/td&gt;
&lt;td&gt;Safari&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/section&gt;
&lt;/section&gt;</code></pre>
</section>

0 comments on commit f81edda

Please sign in to comment.