getreadystack commited on
Commit
f0aeacf
·
verified ·
1 Parent(s): eb35d4c

Upload index.html with huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +210 -17
index.html CHANGED
@@ -1,19 +1,212 @@
1
  <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
1
  <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <title>RED Cybersecurity DoC Lint (EN 18031) — free online check</title>
7
+ <style>
8
+ :root{color-scheme:light}body{margin:0;font:15px/1.55 system-ui,-apple-system,"Segoe UI",sans-serif;background:#faf9f5;color:#1a1512}
9
+ .wrap{max-width:960px;margin:0 auto;padding:28px 18px 60px}h1{font-size:26px;margin:0 0 6px}.lede{color:#4a403a;margin:0 0 16px}
10
+ textarea{width:100%;min-height:260px;font:13px/1.45 ui-monospace,Menlo,Consolas,monospace;padding:12px;border:1px solid #d9d0c4;border-radius:8px;box-sizing:border-box}
11
+ .bar{display:flex;gap:10px;align-items:center;margin:12px 0}button{font:600 15px system-ui;padding:10px 18px;border:0;border-radius:8px;background:#1a1512;color:#fff;cursor:pointer}
12
+ input[type=date]{font:14px system-ui;padding:8px;border:1px solid #d9d0c4;border-radius:6px}
13
+ table{border-collapse:collapse;width:100%;font-size:14px;margin-top:10px}th,td{text-align:left;padding:8px 10px;border-bottom:1px solid #eee;vertical-align:top}th{font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:#7a6e65}
14
+ .sev.error{color:#a8551f;font-weight:700}.sev.warn,.sev.warning{color:#96691f}.ok{color:#2a6446;font-weight:600}.sum{font-weight:600}
15
+ .note{font-size:13px;color:#7a6e65;margin-top:18px}#paid{margin-top:22px;padding:14px 16px;border:1px solid #e2d8cb;border-radius:10px;background:#fffdfa}
16
+ </style>
17
+ <script data-grow-initializer="">!(function(){window.growMe||((window.growMe=function(e){window.growMe._.push(e);}),(window.growMe._=[]));var e=document.createElement("script");(e.type="text/javascript"),(e.src="https://faves.grow.me/main.js"),(e.defer=!0),e.setAttribute("data-grow-faves-site-id","U2l0ZTphZjljMzgyMC0yMmU5LTRhYjgtYTIxNS03OTRhMGY1N2ExYzM=");var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t);})();</script>
18
+ <!--yj-canon-s101--><link rel="canonical" href="https://getreadystack.com/tools/red-doc-en18031-lint"></head>
19
+ <body>
20
+ <div class="wrap">
21
+ <h1>RED Cybersecurity DoC Lint (EN 18031)</h1>
22
+ <p class="lede">Audits an EU Declaration of Conformity for radio equipment against Delegated Regulation (EU) 2022/30 and the EN 18031:2024 citations, mandatory since 1 August 2025. Runs entirely in your browser — nothing is uploaded.</p>
23
+ <textarea id="src" spellcheck="false"># EC Declaration of Conformity
24
+
25
+ Model: WX-2 Smart Plug
26
+ Address: 12 Keji Road, Nanshan, Shenzhen, China
27
+ Firmware version: 1.4.2
28
+
29
+ We declare that the product above conforms to the following directives:
30
+
31
+ - Directive 1999/5/EC (R&amp;TTE)
32
+ - Directive 2011/65/EU (RoHS)
33
+
34
+ Cybersecurity: the product meets the new radio cybersecurity rules that apply from
35
+ 1 August 2024. Testing was carried out against EN 18031-1 by our internal laboratory.
36
+
37
+ This declaration of conformity is issued under the sole responsibility of the manufacturer.
38
+
39
+ Signed for and on behalf of: Shenzhen Example Electronics Co., Ltd
40
+ Place and date of issue: Shenzhen, 2024-11-05
41
+ Name and function: L. Wei, Quality Manager</textarea>
42
+ <div class="bar"><button id="go">Check</button><label>as of <input type="date" id="today"></label></div>
43
+ <div id="out" aria-live="polite"></div>
44
+ <div id="paid"><strong>Free here:</strong> lint the open declaration-of-conformity file against all 18 rules and see every Delegated Regulation (EU) 2022/30 gap with the line it sits on. <strong>Next:</strong> sweep every declaration in the workspace in one pass and write one dated audit report file to keep with the technical documentation — that part asks for a licence key.<br><a class="cta" href="https://buy.polar.sh/polar_cl_5Hm0xLe0JD2dW7YPmdtuS5sX86RiELo7TMeUJ2zEQQr" data-polar-checkout data-polar-checkout-theme="light">Get the workspace sweep and the audit report — $29</a><br><small>$29 once &middot; one licence key per person or CI seat &middot; 7-day full refund. EU RED compliance consultancy is typically billed at $150 to $250 per hour, and a notified body assessment costs far more again.</small></div>
45
+ <p class="note">Same engine as the VS Code extension, byte for byte.</p>
46
+ </div>
47
+ <script>var RED_RULES = [
48
+ {"id":"eu_not_ec_title","kind":"forbid","sev":"warn","bad":"\\bEC declaration of conformity\\b",
49
+ "msg":"Title says \"EC declaration of conformity\". RED Annex VI calls it the EU declaration of conformity; market surveillance reads the title first."},
50
+ {"id":"rtte_repealed","kind":"forbid","sev":"error","bad":"1999/5/EC",
51
+ "msg":"Cites the repealed R\u0026TTE Directive 1999/5/EC. Radio equipment placed on the EU market is covered by Directive 2014/53/EU (RED)."},
52
+ {"id":"red_directive","kind":"require","sev":"error","need":"Directive\\s*2014/53/EU",
53
+ "msg":"No reference to Directive 2014/53/EU. Annex VI point 5 needs the Union harmonisation legislation the object conforms to."},
54
+ {"id":"delegated_2022_30","kind":"require","sev":"error","need":"\\(EU\\)\\s*2022/30",
55
+ "msg":"No reference to Delegated Regulation (EU) 2022/30, the act that switched on the RED cybersecurity essential requirements."},
56
+ {"id":"art_3_3_d","kind":"require","sev":"error","need":"3\\s*\\(\\s*3\\s*\\)\\s*\\(\\s*d\\s*\\)",
57
+ "msg":"Article 3(3)(d) (network protection) is not named. It applies to internet-connected radio equipment under (EU) 2022/30."},
58
+ {"id":"art_3_3_e","kind":"require","sev":"warn","need":"3\\s*\\(\\s*3\\s*\\)\\s*\\(\\s*e\\s*\\)",
59
+ "msg":"Article 3(3)(e) (personal data and privacy) is not named. State that it applies, or state why the equipment does not process personal data."},
60
+ {"id":"art_3_3_f","kind":"require","sev":"warn","need":"3\\s*\\(\\s*3\\s*\\)\\s*\\(\\s*f\\s*\\)",
61
+ "msg":"Article 3(3)(f) (protection from fraud) is not named. State that it applies, or state why the equipment does not transfer money or virtual currency."},
62
+ {"id":"old_2024_date","kind":"forbid","sev":"error","bad":"1\\s*August\\s*2024|2024-08-01|01\\.08\\.2024",
63
+ "msg":"Uses the withdrawn 1 August 2024 date. Delegated Regulation (EU) 2023/2444 moved the application of (EU) 2022/30 to 1 August 2025."},
64
+ {"id":"en18031_edition","kind":"pair","sev":"warn","when":"EN\\s*18031-[123]","need":"EN\\s*18031-[123]\\s*:\\s*2024",
65
+ "msg":"EN 18031 is cited without its 2024 edition. Annex VI point 6 wants the dated reference, e.g. EN 18031-1:2024."},
66
+ {"id":"en18031_restriction","kind":"pair","sev":"error","when":"EN\\s*18031-[123]","need":"restriction",
67
+ "msg":"EN 18031-1/-2/-3 are cited in the Official Journal with restrictions, so the presumption of conformity is not complete. Record the restriction here."},
68
+ {"id":"notified_body","kind":"pair","sev":"error","when":"EN\\s*18031-[123]",
69
+ "need":"notified body[^\\n]{0,80}\\d{4}|\\d{4}[^\\n]{0,40}notified body|restrictions?[^\\n]{0,60}(do not apply|not applicable)",
70
+ "msg":"EN 18031 is cited but no notified body (name + four-digit number) and no statement that the restricted parts do not apply to this product."},
71
+ {"id":"sole_responsibility","kind":"require","sev":"error","need":"sole responsibility of the manufacturer",
72
+ "msg":"Annex VI point 3 sentence is missing: this declaration of conformity is issued under the sole responsibility of the manufacturer."},
73
+ {"id":"object_identifier","kind":"require","sev":"error","need":"(model|type|product|batch|serial)[^\\n]{0,20}:",
74
+ "msg":"Annex VI points 1 and 4 need a traceable identifier of the object: product model, type, batch or serial number."},
75
+ {"id":"manufacturer_address","kind":"require","sev":"error","need":"address\\s*:",
76
+ "msg":"Annex VI point 2 needs the name and the postal address of the manufacturer (or the authorised representative)."},
77
+ {"id":"software_version","kind":"require","sev":"warn","need":"(firmware|software)[^\\n]{0,20}version",
78
+ "msg":"No firmware or software version. Cybersecurity conformity is version-bound, and Annex VI point 8 covers the software the equipment ships with."},
79
+ {"id":"signature_block","kind":"require","sev":"error","need":"signed for and on behalf of|place and date of issue",
80
+ "msg":"Annex VI point 9 is missing: signed for and on behalf of, place and date of issue, name, function, signature."},
81
+ {"id":"issued_before_applicability","kind":"date_min","sev":"error","min":"2025-08-01",
82
+ "msg":"The declaration is dated before 1 August 2025, when the cybersecurity requirements began to apply. It cannot cover (EU) 2022/30 as written."},
83
+ {"id":"declaration_age","kind":"date_age","sev":"warn","max_days":365,
84
+ "msg":"The declaration is more than 12 months old. Re-confirm that every standard it cites is still cited in the Official Journal."}
85
+ ]
86
+ ;</script>
87
+ <script>/* RED Cybersecurity DoC Lint — one brain, used by the extension and by the free web page.
88
+ Reads the rule table from ext/rules.json (node) or window.RED_RULES (browser). */
89
+ var RULES = (typeof module !== 'undefined' && module.exports)
90
+ ? require('./rules.json')
91
+ : (typeof window !== 'undefined' ? window.RED_RULES : []);
92
+
93
+ /* Delegated Regulation (EU) 2022/30 first applied on this date, after (EU) 2023/2444 postponed it. */
94
+ var APPLICABLE_FROM = '2025-08-01';
95
+
96
+ function lineOf(text, index) {
97
+ return text.slice(0, index).split('\n').length;
98
+ }
99
+ function rx(pattern, flags) {
100
+ return new RegExp(pattern, flags || 'i');
101
+ }
102
+ function daysBetween(fromIso, toIso) {
103
+ return Math.round((Date.parse(toIso) - Date.parse(fromIso)) / 86400000);
104
+ }
105
+ function issueDate(text) {
106
+ var m = /(?:place and date of issue|date of issue|issued on|date)\s*:?\s*[^\n]*?(\d{4}-\d{2}-\d{2})/i.exec(text);
107
+ return m ? { iso: m[1], line: lineOf(text, m.index) } : null;
108
+ }
109
+
110
+ function check(text, opts) {
111
+ opts = opts || {};
112
+ var today = opts.today || '2026-09-17';
113
+ var maxAge = Number(opts.review_days) > 0 ? Number(opts.review_days) : 0;
114
+ text = String(text || '');
115
+ var findings = [];
116
+ var date = issueDate(text);
117
+
118
+ for (var i = 0; i < RULES.length; i++) {
119
+ var r = RULES[i];
120
+ if (r.kind === 'require') {
121
+ if (!rx(r.need).test(text)) findings.push({ check: r.id, sev: r.sev, msg: r.msg, line: 1 });
122
+
123
+ } else if (r.kind === 'forbid') {
124
+ var re = rx(r.bad, 'gi'), m;
125
+ while ((m = re.exec(text)) !== null) {
126
+ findings.push({ check: r.id, sev: r.sev, msg: r.msg, line: lineOf(text, m.index) });
127
+ if (m.index === re.lastIndex) re.lastIndex++;
128
+ }
129
+
130
+ } else if (r.kind === 'pair') {
131
+ var w = rx(r.when).exec(text);
132
+ if (w && !rx(r.need).test(text)) {
133
+ findings.push({ check: r.id, sev: r.sev, msg: r.msg, line: lineOf(text, w.index) });
134
+ }
135
+
136
+ } else if (r.kind === 'date_min') {
137
+ if (date) {
138
+ var early = daysBetween(date.iso, r.min || APPLICABLE_FROM);
139
+ if (early > 0) {
140
+ findings.push({
141
+ check: r.id, sev: r.sev, line: date.line,
142
+ msg: r.msg + ' Dated ' + date.iso + ', ' + early + ' days before ' + (r.min || APPLICABLE_FROM) + '.'
143
+ });
144
+ }
145
+ }
146
+
147
+ } else if (r.kind === 'date_age') {
148
+ var limit = maxAge || Number(r.max_days) || 365;
149
+ if (date) {
150
+ var age = daysBetween(date.iso, today);
151
+ if (age > limit) {
152
+ findings.push({
153
+ check: r.id, sev: r.sev, line: date.line,
154
+ msg: r.msg + ' Dated ' + date.iso + ', ' + age + ' days old on ' + today + ' (limit ' + limit + ').'
155
+ });
156
+ }
157
+ }
158
+ }
159
+ }
160
+
161
+ findings.sort(function (a, b) { return a.line - b.line; });
162
+ return { findings: findings };
163
+ }
164
+
165
+ var API = { engine: { check: check }, RULES: RULES, RULE_COUNT: RULES.length };
166
+ if (typeof module !== 'undefined' && module.exports) module.exports = API;
167
+ if (typeof window !== 'undefined') window.RED_ENGINE = API;
168
+ </script>
169
+ <script>// ⛔뼈대 — kit/scaffold.py 가 찍는다 (s143). findings [{check,sev,msg,line?}] → 글/HTML. 같은 파일이 Node 와 브라우저에서 산다.
170
+ 'use strict';
171
+ function escapeHtml(s) { return String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;'); }
172
+ function summaryLine(res) {
173
+ const f = (res && res.findings) || []; const e = f.filter(function (x) { return String(x.sev || 'error').toLowerCase().startsWith('err'); }).length;
174
+ return f.length ? (f.length + ' finding' + (f.length === 1 ? '' : 's') + ' (' + e + ' error' + (e === 1 ? '' : 's') + ')') : 'Clean — no findings.';
175
+ }
176
+ function toText(res, label) {
177
+ const f = (res && res.findings) || [];
178
+ const lines = ['== ' + (label || '') + ' — ' + summaryLine(res)];
179
+ f.forEach(function (x) { lines.push(' ' + String(x.sev || 'error').toUpperCase().slice(0, 4) + ' ' + (x.line ? 'L' + x.line + ' ' : '') + (x.check || x.id || '') + ' ' + (x.msg || x.message || '')); });
180
+ return lines.join('\n');
181
+ }
182
+ function toHtml(res) {
183
+ const f = (res && res.findings) || [];
184
+ if (!f.length) return '<p class="ok">' + escapeHtml(summaryLine(res)) + '</p>';
185
+ const rows = f.map(function (x) { return '<tr><td class="sev ' + escapeHtml(String(x.sev || 'error')) + '">' + escapeHtml(String(x.sev || 'error')) + '</td><td>' + (x.line ? 'L' + escapeHtml(x.line) : '') + '</td><td><code>' + escapeHtml(x.check || x.id || '') + '</code></td><td>' + escapeHtml(x.msg || x.message || '') + '</td></tr>'; }).join('');
186
+ return '<p class="sum">' + escapeHtml(summaryLine(res)) + '</p><table><thead><tr><th>Level</th><th>Line</th><th>Check</th><th>What</th></tr></thead><tbody>' + rows + '</tbody></table>';
187
+ }
188
+ var RED_REPORT = { escapeHtml: escapeHtml, summaryLine: summaryLine, toText: toText, toHtml: toHtml };
189
+ if (typeof module !== 'undefined' && module.exports) module.exports = RED_REPORT;
190
+ else window.RED_REPORT = RED_REPORT;
191
+ </script>
192
+ <script>
193
+ (function(){
194
+ var src=document.getElementById('src'), out=document.getElementById('out'), go=document.getElementById('go'), today=document.getElementById('today');
195
+ today.value=new Date().toISOString().slice(0,10);
196
+ function run(){ try { var res=window.RED_ENGINE.engine.check(src.value,{today:today.value}); out.innerHTML=window.RED_REPORT.toHtml(res); } catch(e){ out.innerHTML='<p class="sev error">Could not run: '+String(e.message||e)+'</p>'; } }
197
+ go.onclick=run; if (src.value.trim()) run();
198
+ })();
199
+ </script>
200
+ <script defer data-auto-init src="https://cdn.jsdelivr.net/npm/@polar-sh/checkout@latest/dist/embed.global.js"></script>
201
+
202
+
203
+ <section data-yj-install="free" style="margin:2rem auto 1rem;max-width:46rem;padding:1.25rem 1.25rem;border:1px solid #cfe3d6;border-radius:12px;background:#f6fbf8;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif"><h2 style="margin:0 0 .4rem;font-size:1.2rem">Install free</h2><p style="margin:0 0 .8rem;color:#41505f">Free for the file open in your editor - no key, no limit. The workspace sweep and the report ask for a key.</p><a href="https://open-vsx.org/extension/readystack/red-doc-en18031-lint" rel="noopener" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">Open VSX (Cursor, VSCodium)</a><a href="https://www.npmjs.com/package/@readystack/red-doc-en18031-lint" rel="noopener" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">npm</a><a href="https://hub.docker.com/r/getreadystack/red-doc-en18031-lint" rel="noopener" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">Docker Hub</a><pre style="margin:.5rem 0 0;padding:.6rem .8rem;background:#f3f5f8;border-radius:8px;font-size:.9rem;overflow:auto">npx @readystack/red-doc-en18031-lint &lt;file&gt;
204
+ docker run --rm -v &quot;$PWD:/w&quot; getreadystack/red-doc-en18031-lint /w</pre><p style="margin:.6rem 0 0;font-size:.92rem;color:#41505f"><a href="https://buy.polar.sh/polar_cl_l6iN1uWt0FwWu7tBsczD0jWpP2vxFM54Wdwqb3KPi1G" rel="nofollow" style="color:#0f7b3f;text-decoration:underline">Team? One key for every ReadyStack linter, 5 seats, $149 once</a></p></section>
205
+ <section data-yj-alert="rule" style="margin:1rem auto 1.5rem;max-width:46rem;padding:1.1rem 1.25rem;border:1px solid #d9dee6;border-radius:12px;background:#fbfcfd;font:15px/1.55 system-ui,-apple-system,Segoe UI,sans-serif"><b style="font-size:1.05rem">Get one email when this rule changes</b><div style="opacity:.78;margin:.35rem 0 .8rem">We watch the regulation and vendor sources behind RED Cybersecurity DoC Lint (EN 18031) every day. When a rule changes, you get a single email with what changed and the updated check. No newsletter.</div><div style="display:flex;gap:8px;flex-wrap:wrap"><input id="yjae" type="email" placeholder="you@example.com" style="flex:1;min-width:210px;padding:11px 13px;border:1px solid rgba(140,150,165,.34);border-radius:8px;background:#fff;color:inherit"><button id="yjab" style="padding:11px 18px;border-radius:8px;border:0;cursor:pointer;background:#0f7b3f;color:#fff;font:600 15px system-ui,sans-serif">Notify me</button></div><div id="yjao" hidden style="margin-top:.6rem;color:#0f7b3f">You're on the list. One email when it changes.</div><script>(function(){var b=document.getElementById("yjab"),e=document.getElementById("yjae");if(!b||!e)return;b.addEventListener("click",function(){var v=e.value.trim();if(!/.+@.+\..+/.test(v))return;try{localStorage.setItem("yj_em","1");}catch(_){}fetch(location.origin+"/api/subscribe",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:v,slug:"red-doc-en18031-lint",lang:"en",source:"rule_alert"})}).then(function(r){var o=document.getElementById("yjao");o.hidden=false;if(!r.ok){o.textContent="Could not save - please try again.";}}).catch(function(){var o=document.getElementById("yjao");o.hidden=false;o.textContent="Could not save - please try again.";});});})();</script></section>
206
+
207
+ <section data-yj-cta="paid" style="margin:3rem auto;max-width:46rem;padding:1.5rem 1.25rem;border:1px solid #d8dee9;border-radius:12px;background:#fbfcfe;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif"><h2 style="margin:0 0 .5rem;font-size:1.25rem">Get the complete version <span class="yj-price">$29</span></h2><p style="margin:.25rem 0 1rem;color:#41505f">This page is the working piece. The full pack has everything below.</p><p style="margin:0 0 1rem;color:#41505f">Checks an EU declaration of conformity for radio equipment against Delegated Regulation (EU) 2022/30 and the EN 18031:2024 citations</p><p style="margin:0 0 1rem;color:#5b6b7c;font-size:.94rem">EU RED compliance consultancy is typically billed at $150 to $250 per hour, and a notified body assessment costs far more again</p><a href="https://buy.polar.sh/polar_cl_5Hm0xLe0JD2dW7YPmdtuS5sX86RiELo7TMeUJ2zEQQr" rel="nofollow" style="display:inline-block;padding:.7rem 1.3rem;border-radius:8px;background:#1b64f2;color:#fff;text-decoration:none;font-weight:600">Buy the full version — $29</a></section>
208
+ <section data-yj="yj-facts-v1" style="max-width:920px;margin:48px auto 0;padding:0 20px;font-family:system-ui,sans-serif"><style>.yj-article p{font:400 15.5px/1.7 system-ui,sans-serif;color:#26313b;margin:0 0 12px;max-width:72ch}.yj-article h2,.yj-article h3,.yj-article h4{font:600 17px/1.35 system-ui,sans-serif;color:#1b1f24;margin:22px 0 8px}.yj-article table{border-collapse:collapse;margin:10px 0 16px;font:14px/1.45 system-ui,sans-serif}.yj-article th,.yj-article td{border:1px solid #e2e6ea;padding:6px 10px;text-align:left}.yj-article th{background:#f4f6f8}.yj-article pre{background:#0f1720;color:#e6edf3;padding:12px 14px;border-radius:8px;overflow:auto;font:13px/1.5 ui-monospace,Menlo,monospace}.yj-article code{font:13px ui-monospace,Menlo,monospace;background:#f1f3f5;padding:1px 4px;border-radius:3px}.yj-article pre code{background:none;padding:0}.yj-article ul,.yj-article ol{font:15px/1.6 system-ui,sans-serif;color:#26313b}</style><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:34px 0 6px;color:#1b1f24">Questions people ask</h2><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What does it actually check?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">It reads a declaration of conformity written as Markdown in your repository and checks it against 18 rules taken from Annex VI of Directive 2014/53/EU and from Delegated Regulation (EU) 2022/30. Every finding names the line, the article behind it and what the line should say instead. The bundled legacy sample returns 13 findings.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Who is this for?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Firmware and compliance engineers at radio and IoT manufacturers who place Wi-Fi, Bluetooth or cellular products on the EU market, and the importers who must keep the declaration for ten years. If the declaration lives in the repository next to the firmware it describes, this runs where that file already is.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Why will a free template or a chatbot not do?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Templates in circulation still carry 1 August 2024, the date that Delegated Regulation (EU) 2023/2444 replaced with 1 August 2025, and a generic template has no field for the restrictions attached to the EN 18031:2024 citations or for the notified body those restrictions can require. A spell checker sees none of it.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What is free and what is paid?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Free: lint the open file against all 18 rules, 12 error-level and 6 advisory, with line numbers, in VS Code or in the browser. Paid at $29 once: sweep every declaration in the workspace in one pass and write a dated audit report file you can file with the technical documentation.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What would this cost with a person?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">EU RED compliance consultancy is typically billed at $150 to $250 per hour, and a declaration review is rarely the only line on the invoice; a notified body assessment costs far more again. This checks the paperwork you control before it reaches either desk, for $29 once with a 7-day full refund.</p></details><script type="application/ld+json" data-yj="yj-faq-ld">{"@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [{"@type": "Question", "name": "What does it actually check?", "acceptedAnswer": {"@type": "Answer", "text": "It reads a declaration of conformity written as Markdown in your repository and checks it against 18 rules taken from Annex VI of Directive 2014/53/EU and from Delegated Regulation (EU) 2022/30. Every finding names the line, the article behind it and what the line should say instead. The bundled legacy sample returns 13 findings."}}, {"@type": "Question", "name": "Who is this for?", "acceptedAnswer": {"@type": "Answer", "text": "Firmware and compliance engineers at radio and IoT manufacturers who place Wi-Fi, Bluetooth or cellular products on the EU market, and the importers who must keep the declaration for ten years. If the declaration lives in the repository next to the firmware it describes, this runs where that file already is."}}, {"@type": "Question", "name": "Why will a free template or a chatbot not do?", "acceptedAnswer": {"@type": "Answer", "text": "Templates in circulation still carry 1 August 2024, the date that Delegated Regulation (EU) 2023/2444 replaced with 1 August 2025, and a generic template has no field for the restrictions attached to the EN 18031:2024 citations or for the notified body those restrictions can require. A spell checker sees none of it."}}, {"@type": "Question", "name": "What is free and what is paid?", "acceptedAnswer": {"@type": "Answer", "text": "Free: lint the open file against all 18 rules, 12 error-level and 6 advisory, with line numbers, in VS Code or in the browser. Paid at $29 once: sweep every declaration in the workspace in one pass and write a dated audit report file you can file with the technical documentation."}}, {"@type": "Question", "name": "What would this cost with a person?", "acceptedAnswer": {"@type": "Answer", "text": "EU RED compliance consultancy is typically billed at $150 to $250 per hour, and a declaration review is rarely the only line on the invoice; a notified body assessment costs far more again. This checks the paperwork you control before it reaches either desk, for $29 once with a 7-day full refund."}}]}</script><div id="yj-ask" style="margin:36px 0 0;padding:18px 18px 16px;border:1px solid #e2e6ea;border-radius:10px;background:#fbfbfc"><h2 style="font:600 19px/1.3 system-ui,sans-serif;margin:0 0 4px;color:#1b1f24">Ask about this tool</h2><p style="font:400 13.5px/1.5 system-ui,sans-serif;margin:0 0 12px;color:#5b6570">One question, answered by the person who built it. Your email only if you want the answer sent.</p><form onsubmit="return yjAsk(event)" style="display:grid;gap:8px"><textarea name="question" required minlength="10" maxlength="2000" rows="3" placeholder="Your question" style="font:14px/1.5 system-ui,sans-serif;padding:10px;border:1px solid #cfd6dd;border-radius:6px"></textarea><div style="display:flex;gap:8px;flex-wrap:wrap"><input type="email" name="email" placeholder="Email (optional)" style="flex:1;min-width:200px;font:14px system-ui,sans-serif;padding:9px 10px;border:1px solid #cfd6dd;border-radius:6px"><button type="submit" style="font:600 14px system-ui,sans-serif;padding:9px 18px;border:0;border-radius:6px;background:#1b1f24;color:#fff;cursor:pointer">Send</button></div><p id="yj-ask-msg" style="font:13px system-ui,sans-serif;margin:2px 0 0;color:#0a6238;min-height:1em"></p></form><script>function yjAsk(e){e.preventDefault();var f=e.target,m=document.getElementById("yj-ask-msg");m.style.color="#0a6238";fetch(location.origin+"/api/ask",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sku:0,slug:"red-doc-en18031-lint",lang:"en",question:f.question.value,email:f.email.value,page:location.pathname})}).then(function(r){if(!r.ok)throw 0;m.textContent="Thanks \u2014 noted. Answers land on this page and, if you left an email, in your inbox.";f.question.value="";}).catch(function(){m.style.color="#a8551f";m.textContent="Could not send. Please try again in a minute.";});return false;}</script></div></section><section class="yj-related" style="max-width:920px;margin:56px auto 40px;padding:0 20px"><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:0 0 6px;color:#1b1f24">Same job, next tool</h2><p style="font:400 14.5px/1.5 system-ui,sans-serif;margin:0 0 20px;color:#5b6570">Free in the browser. The full version is a one-time licence, 7-day refund.</p><div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:14px"><a class="yj-rel-c" href="https://getreadystack.com/tools/en18031-psti-lint"><span class="yj-rel-t">EN 18031 / PSTI Device Config Lint</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/autohotkey-toml-devicetree-snippets"><span class="yj-rel-t">AutoHotkey v2, TOML and DeviceTree checks for VS Code</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/firmware-release-gate"><span class="yj-rel-t">Firmware Release Gate for sdkconfig and prj.conf</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/svg-asset-compliance-lint"><span class="yj-rel-t">SVG Asset Compliance Lint</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/wordpress-ada-compliance-plugin"><span class="yj-rel-t">ADA Compliance Plugin for WordPress: Title II Grievance Form</span><span class="yj-rel-p">$60</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/revit-window-family"><span class="yj-rel-t">Revit Window Family Starter Blocks — 12 Dimensioned DXF Window Blocks for Impo</span><span class="yj-rel-p">$100</span></a></div><style>.yj-rel-c{display:flex;flex-direction:column;gap:8px;padding:15px 16px;border:1px solid #e2e6ea;border-radius:6px;text-decoration:none;background:#fff}.yj-rel-c:hover{border-color:#b9c2cb;background:#fafbfc}.yj-rel-t{font:500 14.5px/1.42 system-ui,sans-serif;color:#1b1f24}.yj-rel-p{font:600 13px system-ui,sans-serif;color:#0a6238}</style></section><!--yj-share-s101--><div style="margin:28px 0 8px;text-align:center"><button id="yjcp" type="button" style="font:inherit;padding:10px 18px;border:1px solid #8884;border-radius:10px;background:transparent;cursor:pointer">Copy link</button><button id="yjimg" type="button" style="font:inherit;padding:10px 18px;margin-left:8px;border:1px solid #8884;border-radius:10px;background:transparent;cursor:pointer">Save result as image</button></div><script>(function(){var b=document.getElementById("yjimg");if(!b)return;b.addEventListener("click",function(){var o=document.getElementById("out");var txt=(o&&(o.innerText||o.textContent)||"").trim();if(!txt){b.textContent="(no result yet)";setTimeout(function(){b.textContent="Save result as image";},1500);return;}var lines=txt.split(String.fromCharCode(10)).filter(function(x){return x.trim();}).slice(0,10);var W=1200,P=56,c=document.createElement("canvas");c.width=W;var lh=38,H=P*2+70+lines.length*lh+60;c.height=H;var x=c.getContext("2d");x.fillStyle="#1a1512";x.fillRect(0,0,W,H);x.fillStyle="#f3e9d2";x.font="600 34px system-ui,Segoe UI,Arial";var t=(document.title||"").split("|")[0].trim();x.fillText(t.slice(0,54),P,P+34);x.font="22px ui-monospace,Menlo,Consolas,monospace";x.fillStyle="#e8dcc4";for(var i=0;i<lines.length;i++){x.fillText(lines[i].slice(0,88),P,P+70+i*lh+22);}x.font="600 22px system-ui,Segoe UI,Arial";x.fillStyle="#c9a227";var d=location.hostname.replace("www.","");x.fillText(d,W-P-x.measureText(d).width,H-P+6);c.toBlob(function(bl){var u=URL.createObjectURL(bl),a=document.createElement("a");a.href=u;a.download=(t||"result").replace(/[^a-z0-9]+/gi,"-").toLowerCase()+"-"+d+".png";document.body.appendChild(a);a.click();setTimeout(function(){URL.revokeObjectURL(u);a.remove();},2000);},"image/png");});})();</script><script>(function(){var b=document.getElementById("yjcp");if(!b)return;var t=b.textContent;b.addEventListener("click",function(){var u=location.href.split("#")[0];function d(){b.textContent="Link copied";setTimeout(function(){b.textContent=t;},1800);}if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(u).then(d,function(){prompt("",u);});}else{prompt("",u);}});})();</script>
209
+ <script data-yj="yj-view-beacon">(function(){try{var p=location.pathname;var k='yjv:'+p;if(sessionStorage.getItem(k))return;sessionStorage.setItem(k,'1');fetch('/api/ev',{method:'POST',keepalive:true,headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p,lang:"en",ref:(document.referrer||'')})}).catch(function(){});}catch(e){}})();</script><div class="yj-home-find"><div class="yj-lgbar"><a href="/" class="yj-lg on">EN</a><a href="/de/" class="yj-lg">DE</a><a href="/ja/" class="yj-lg">JA</a><a href="/es/" class="yj-lg">ES</a><a href="/pt/" class="yj-lg">PT</a></div><section class="yj-find"><h2>Find a tool</h2><input id="yjq" type="search" autocomplete="off" placeholder="Type a product name, format or task"><div id="yjr"></div></section><style>.yj-lgbar{position:absolute;top:14px;right:18px;display:flex;gap:6px;z-index:60}.yj-lg{font:600 12px/1 system-ui,sans-serif;padding:6px 9px;border-radius:4px;text-decoration:none;color:#8b96a3;border:1px solid rgba(140,150,165,.28)}.yj-lg:hover{color:#e8eaed;border-color:rgba(160,175,195,.6)}.yj-lg.on{color:#0e1116;background:#cfd6de;border-color:#cfd6de}.yj-find{max-width:760px;margin:34px auto 8px;padding:0 20px}.yj-find h2{font:600 20px/1.3 system-ui,sans-serif;margin:0 0 10px}#yjq{width:100%;box-sizing:border-box;padding:13px 15px;font:400 15.5px system-ui,sans-serif;border:1px solid rgba(140,150,165,.34);border-radius:8px;background:rgba(255,255,255,.04);color:inherit}#yjq:focus{outline:none;border-color:#7FD1C4}#yjr{margin-top:10px;display:flex;flex-direction:column;gap:6px}#yjr a{display:flex;justify-content:space-between;gap:12px;padding:11px 14px;border:1px solid rgba(140,150,165,.22);border-radius:6px;text-decoration:none;font:400 14.5px/1.4 system-ui,sans-serif;color:inherit}#yjr a:hover{border-color:#7FD1C4}#yjr .pr{font:600 13px system-ui,sans-serif;color:#5fbf9a;white-space:nowrap}</style><script>(function(){var q=document.getElementById("yjq"),r=document.getElementById("yjr"),D=null;function load(){if(D)return Promise.resolve(D);return fetch("/search-index.json").then(function(x){return x.json();}).then(function(j){D=j;return j;}).catch(function(){D=[];return D;});}function esc(t){return String(t).replace(/[&<>"]/g,function(c){return {"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;"}[c];});}function run(){var v=q.value.trim().toLowerCase();if(v.length<2){r.innerHTML="";return;}load().then(function(j){var w=v.split(/\s+/),o=[];for(var i=0;i<j.length&&o.length<12;i++){var t=j[i].t.toLowerCase();var ok=true;for(var k=0;k<w.length;k++){if(t.indexOf(w[k])<0){ok=false;break;}}if(ok)o.push(j[i]);}r.innerHTML=o.length?o.map(function(x){return "<a href=\""+esc(x.u)+"\">"+"<span>"+esc(x.t)+"</span>"+(x.p?"<span class=\"pr\">$"+x.p+"</span>":"")+"</a>";}).join(""):"";});}q.addEventListener("input",run);q.addEventListener("focus",load);})();</script></div>
210
+ <script data-yj="yj-use-beacon">(function(){try{var o=document.getElementById('out');if(!o)return;var p=location.pathname,k='yju:'+p,sent=false;function fire(){if(sent||sessionStorage.getItem(k))return;if(!(o.textContent||'').replace(/\s+/g,'').length)return;sent=true;sessionStorage.setItem(k,'1');fetch('/api/ev',{method:'POST',keepalive:true,headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p,lang:"en",t:'use'})}).catch(function(){});}var mo=new MutationObserver(function(){fire();if(sent)mo.disconnect();});mo.observe(o,{childList:true,characterData:true,subtree:true});}catch(e){}})();</script>
211
+ </body>
212
  </html>