File size: 43,362 Bytes
fac3b1c f538081 fac3b1c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | <!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>JavaScript commercial license check — check commercial keys free</title>
<meta name="description" content="This browser tool flags GPL and evaluation licence keys and missing commercial keys for listed JavaScript and TypeScript libraries in closed-source code.">
<style>
:root{color-scheme:light}body{margin:0;font:15px/1.55 system-ui,-apple-system,"Segoe UI",sans-serif;background:#faf9f5;color:#1a1512}
.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}
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}
.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}
input[type=date]{font:14px system-ui;padding:8px;border:1px solid #d9d0c4;border-radius:6px}
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}
.sev.error{color:#a8551f;font-weight:700}.sev.warn,.sev.warning{color:#96691f}.ok{color:#2a6446;font-weight:600}.sum{font-weight:600}
.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}
</style>
<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>
<!--yj-canon-s101--><link rel="canonical" href="https://getreadystack.com/tools/js-licence-key-gate"></head>
<body>
<div class="wrap">
<h1>JavaScript commercial license check — check commercial keys free</h1>
<p class="lede">Flags GPL and evaluation licence keys and missing commercial keys for Handsontable, TinyMCE, CKEditor 5, FullCalendar, AG Grid, MUI X and Syncfusion in closed-source JS/TS code. Runs entirely in your browser — nothing is uploaded.</p>
<textarea id="src" spellcheck="false">// src/app/widgets.ts: bootstrap for the invoicing SaaS dashboard (closed source)
import Handsontable from 'handsontable';
import { Calendar } from '@fullcalendar/core';
import resourceTimelinePlugin from '@fullcalendar/resource-timeline';
import tinymce from 'tinymce';
import { ClassicEditor, Essentials, Paragraph } from 'ckeditor5';
import { AllEnterpriseModule, ModuleRegistry } from 'ag-grid-enterprise';
import { DataGridPro } from '@mui/x-data-grid-pro';
import mapboxgl from 'mapbox-gl';
ModuleRegistry.registerModules([AllEnterpriseModule]);
export function mountSheet(el: HTMLElement, rows: unknown[][]) {
return new Handsontable(el, {
data: rows,
colHeaders: true,
licenseKey: 'non-commercial-and-evaluation',
});
}
export function mountCalendar(el: HTMLElement) {
const cal = new Calendar(el, {
plugins: [resourceTimelinePlugin],
initialView: 'resourceTimelineWeek',
schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source',
});
cal.render();
return cal;
}
export function mountNotes(selector: string) {
return tinymce.init({
selector,
license_key: 'gpl',
menubar: false,
});
}
export function mountContract(el: HTMLElement) {
return ClassicEditor.create(el, {
licenseKey: 'GPL',
plugins: [Essentials, Paragraph],
});
}
export function mountMap(el: HTMLElement, token: string) {
mapboxgl.accessToken = token;
return new mapboxgl.Map({ container: el, style: 'mapbox://styles/mapbox/streets-v12' });
}
export { DataGridPro };</textarea>
<div class="bar"><button id="go">Check</button><label>as of <input type="date" id="today"></label></div>
<div id="out" aria-live="polite"></div>
<div id="paid"><strong>Free here:</strong> Check one open JS/TS file for GPL, evaluation and missing commercial licence keys, with the line and the fix. <strong>In the editor:</strong> Scan every file in the workspace in one pass and export the licence inventory (CSV + Markdown) for procurement or due diligence — that part asks for a licence key.</div>
<p class="note">Same engine as the VS Code extension, byte for byte.</p>
</div>
<script>var JLK_RULES = [
{"id":"HOT_EVAL_KEY","sev":"error","type":"present","pattern":"licenseKey\\s*:\\s*['\"`]non-commercial-and-evaluation['\"`]","flags":"","msg":"Handsontable key 'non-commercial-and-evaluation' covers non-commercial use and evaluation only; Handsontable is proprietary since 7.0.0.","fix":"Load a purchased Handsontable key from config, or pin handsontable 6.2.2 (the last MIT release)."},
{"id":"HOT_NO_KEY","sev":"warning","type":"absent","when":"from\\s+['\"](handsontable|@handsontable/(react|react-wrapper|angular|angular-wrapper|vue|vue3))['\"]|new\\s+Handsontable\\s*\\(","need":"licenseKey","flags":"","msg":"Handsontable is imported but this file sets no licenseKey; since 7.0.0 every instance needs a commercial key or the evaluation key.","fix":"Pass licenseKey from your config (purchased key) to every Handsontable instance."},
{"id":"FC_GPL_KEY","sev":"error","type":"present","pattern":"['\"`]GPL-My-Project-Is-Open-Source['\"`]","flags":"","msg":"FullCalendar Premium key 'GPL-My-Project-Is-Open-Source' is only valid when your whole project is released under the GPL.","fix":"Buy a FullCalendar Premium licence and set schedulerLicenseKey from config, or drop the premium plugins."},
{"id":"FC_CC_KEY","sev":"error","type":"present","pattern":"['\"`]CC-Attribution-NonCommercial-NoDerivatives['\"`]","flags":"","msg":"FullCalendar Premium key 'CC-Attribution-NonCommercial-NoDerivatives' forbids commercial use.","fix":"Buy a FullCalendar Premium licence and set schedulerLicenseKey from config."},
{"id":"FC_PREMIUM_NO_KEY","sev":"warning","type":"absent","when":"['\"]@fullcalendar/(resource|resource-timeline|resource-timegrid|resource-daygrid|timeline|scrollgrid|adaptive|premium-common)['\"]","need":"schedulerLicenseKey","flags":"","msg":"A FullCalendar Premium plugin is imported but this file sets no schedulerLicenseKey.","fix":"Set schedulerLicenseKey from config (purchased key) in the calendar options."},
{"id":"TINYMCE_GPL_KEY","sev":"error","type":"present","pattern":"license_key\\s*:\\s*['\"`]gpl['\"`]|licenseKey\\s*=\\s*\\{?\\s*['\"`]gpl['\"`]","flags":"i","msg":"TinyMCE license_key 'gpl' declares GPLv2+ use; TinyMCE 7.0 and later are GPLv2+ unless you hold a commercial key.","fix":"Use a commercial TinyMCE key from config, the Tiny Cloud apiKey, or pin tinymce 6.8.x (MIT)."},
{"id":"TINYMCE_NO_KEY","sev":"warning","type":"absent","when":"from\\s+['\"](tinymce|@tinymce/tinymce-(react|vue|angular))['\"]|tinymce\\.init\\s*\\(","need":"license_key|licenseKey|apiKey","flags":"","msg":"TinyMCE is loaded but this file sets no license_key or apiKey; self-hosted TinyMCE 7+ asks for a commercial key or license_key 'gpl'.","fix":"Set license_key from config (commercial key) or use the Tiny Cloud apiKey."},
{"id":"CKEDITOR_GPL_KEY","sev":"error","type":"present","pattern":"licenseKey\\s*:\\s*['\"`]GPL['\"`]","flags":"","msg":"CKEditor 5 licenseKey 'GPL' declares GPL 2+ use of the editor inside this product.","fix":"Set a commercial CKEditor licenseKey from config, or ship the product under a GPL-compatible licence."},
{"id":"CKEDITOR_NO_KEY","sev":"warning","type":"absent","when":"from\\s+['\"](ckeditor5|@ckeditor/ckeditor5-[a-z0-9-]+)['\"]","need":"licenseKey","flags":"","msg":"CKEditor 5 is imported but this file sets no licenseKey; since v44.0.0 config.licenseKey is required.","fix":"Set licenseKey from config: your commercial key, or 'GPL' only for GPL-licensed products."},
{"id":"AGGRID_NO_KEY","sev":"warning","type":"absent","when":"['\"](ag-grid-enterprise|@ag-grid-enterprise/[a-z0-9-]+)['\"]","need":"setLicenseKey","flags":"","msg":"AG Grid Enterprise is imported but this file never calls setLicenseKey; Enterprise is paid per developer ($999 perpetual per developer, AG Grid list price).","fix":"Call LicenseManager.setLicenseKey(\u003ckey from config\u003e) before the first grid renders, or use ag-grid-community only."},
{"id":"MUIX_NO_KEY","sev":"warning","type":"absent","when":"['\"]@mui/x-(data-grid|date-pickers|tree-view|charts|scheduler)-(pro|premium)['\"]","need":"setLicenseKey","flags":"","msg":"An MUI X Pro/Premium package is imported but this file never calls LicenseInfo.setLicenseKey.","fix":"Call LicenseInfo.setLicenseKey(\u003ckey from config\u003e) at app start, or switch to the MIT @mui/x-* package."},
{"id":"SYNCFUSION_NO_KEY","sev":"warning","type":"absent","when":"['\"]@syncfusion/[a-z0-9-]+['\"]","need":"registerLicense","flags":"","msg":"A Syncfusion package is imported but this file never calls registerLicense; the free Community licence needs under $1M revenue, 5 or fewer developers and 10 or fewer employees.","fix":"Call registerLicense(\u003ckey from config\u003e) at app start with a paid or Community key."},
{"id":"MAPBOX_GL_V2","sev":"warning","type":"present","pattern":"from\\s+['\"]mapbox-gl['\"]|require\\(\\s*['\"]mapbox-gl['\"]\\s*\\)","flags":"","msg":"mapbox-gl 2.0.0 and later are proprietary (Mapbox Terms of Service, billed per map load); 1.13 was the last BSD-3 release.","fix":"Keep a Mapbox account and budget map loads, or move to maplibre-gl (BSD-3 fork of 1.13)."},
{"id":"DHTMLX_GANTT_GPL","sev":"warning","type":"present","pattern":"from\\s+['\"]dhtmlx-gantt['\"]|require\\(\\s*['\"]dhtmlx-gantt['\"]\\s*\\)","flags":"","msg":"The npm package dhtmlx-gantt is the Standard edition under GPLv2.","fix":"Buy a DHTMLX Gantt commercial licence and install the commercial build, or ship under the GPL."},
{"id":"HIGHCHARTS_COMMERCIAL","sev":"info","type":"present","pattern":"from\\s+['\"](highcharts|highcharts-react-official|highcharts/[a-z0-9/-]+)['\"]","flags":"","msg":"Highcharts is free for personal, school and non-profit use only; a commercial product needs a Highcharts licence.","fix":"Record the Highcharts licence number for this product, or move to an MIT/Apache chart library."}
]
;</script>
<script>/* js-licence-key-gate engine: one file in, licence-key findings out. Same file runs in node and the browser. */
(function () {
var DOC = (typeof module !== 'undefined' && typeof require !== 'undefined') ? require('./rules.json') : (typeof window !== 'undefined' ? window.JLK_RULES : []);
var RULES = Array.isArray(DOC) ? DOC : (DOC && DOC.rules) || [];
function lineAt(text, idx) {
var n = 1;
for (var i = 0; i < idx && i < text.length; i++) if (text.charCodeAt(i) === 10) n++;
return n;
}
function check(text, opts) {
text = String(text || '').replace(/\r\n?/g, '\n');
var findings = [];
RULES.forEach(function (r) {
var flags = 'g' + (r.flags || '');
if (r.type === 'present') {
var re = new RegExp(r.pattern, flags), m;
while ((m = re.exec(text)) !== null) {
findings.push({ check: r.id, sev: r.sev, msg: r.msg + ' Fix: ' + r.fix, line: lineAt(text, m.index) });
if (m[0] === '') re.lastIndex++;
}
} else if (r.type === 'absent') {
var w = new RegExp(r.when, flags).exec(text);
if (w && !new RegExp(r.need, r.flags || '').test(text)) {
findings.push({ check: r.id, sev: r.sev, msg: r.msg + ' Fix: ' + r.fix, line: lineAt(text, w.index) });
}
}
});
findings.sort(function (a, b) { return a.line - b.line; });
return { findings: findings };
}
var API = { engine: { check: check }, RULES: RULES, RULE_COUNT: RULES.length };
if (typeof module !== 'undefined' && module.exports) module.exports = API;
if (typeof window !== 'undefined') window.JLKENGINE = API;
})();
</script>
<script>// ⛔뼈대 — kit/scaffold.py 가 찍는다 (s143). findings [{check,sev,msg,line?}] → 글/HTML. 같은 파일이 Node 와 브라우저에서 산다.
'use strict';
function escapeHtml(s) { return String(s == null ? '' : s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"'); }
function summaryLine(res) {
const f = (res && res.findings) || []; const e = f.filter(function (x) { return String(x.sev || 'error').toLowerCase().startsWith('err'); }).length;
return f.length ? (f.length + ' finding' + (f.length === 1 ? '' : 's') + ' (' + e + ' error' + (e === 1 ? '' : 's') + ')') : 'Clean — no findings.';
}
function toText(res, label) {
const f = (res && res.findings) || [];
const lines = ['== ' + (label || '') + ' — ' + summaryLine(res)];
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 || '')); });
return lines.join('\n');
}
function toHtml(res) {
const f = (res && res.findings) || [];
if (!f.length) return '<p class="ok">' + escapeHtml(summaryLine(res)) + '</p>';
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('');
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>';
}
var JLKREPORT = { escapeHtml: escapeHtml, summaryLine: summaryLine, toText: toText, toHtml: toHtml };
if (typeof module !== 'undefined' && module.exports) module.exports = JLKREPORT;
else window.JLKREPORT = JLKREPORT;
</script>
<script>
(function(){
var src=document.getElementById('src'), out=document.getElementById('out'), go=document.getElementById('go'), today=document.getElementById('today');
today.value=new Date().toISOString().slice(0,10);
function run(){ try { var res=window.JLKENGINE.engine.check(src.value,{today:today.value}); out.innerHTML=window.JLKREPORT.toHtml(res); } catch(e){ out.innerHTML='<p class="sev error">Could not run: '+String(e.message||e)+'</p>'; } }
go.onclick=run; if (src.value.trim()) run();
})();
</script>
<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/js-licence-key-gate" rel="noopener" data-yj-install-door="ovsx" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'js-licence-key-gate',src:'ovsx',path:location.pathname})],{type:'application/json'}))}catch(e){}" 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/js-licence-key-gate" rel="noopener" data-yj-install-door="npm" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'js-licence-key-gate',src:'npm',path:location.pathname})],{type:'application/json'}))}catch(e){}" 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/js-licence-key-gate" rel="noopener" data-yj-install-door="docker" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'js-licence-key-gate',src:'docker',path:location.pathname})],{type:'application/json'}))}catch(e){}" 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/js-licence-key-gate <file>
docker run --rm -v "$PWD:/w" getreadystack/js-licence-key-gate /w</pre><p style="margin:.6rem 0 0;font-size:.92rem;color:#41505f"><a href="https://getreadystack.com/api/buy/cl/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>
<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 the full rule table as a PDF</b><div style="opacity:.78;margin:.35rem 0 .8rem">All 15 rules JS Licence Key Gate: GPL & Eval Keys checks, each with its source and date, on printable pages you can hand to your team or auditor. We email it now, and once more only if a rule changes. 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">Email me the PDF</button></div><div id="yjao" hidden style="margin-top:.6rem;color:#0f7b3f">Sent. It arrives within the hour - check spam too.</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:"js-licence-key-gate",lang:"en",source:"rule_table"+((b.closest&&b.closest("section")&&b.closest("section").getAttribute("data-yj-moved"))?"_at_result":"")})}).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><script>(function(){var e=document.getElementById("yjae"),s=e&&e.closest?e.closest("section"):null,o=document.getElementById("out");if(!s||!o)return;var d=false;function mv(ev){if(d)return;if(ev&&ev.target&&s.contains(ev.target))return;d=true;var b=o;while(b.parentNode&&b.parentNode!==document.body&&b.parentNode.tagName!=="MAIN"&&b.parentNode.tagName!=="ARTICLE")b=b.parentNode;if(!b.parentNode||b===s||b.contains(s))return;try{b.parentNode.insertBefore(s,b.nextSibling);s.setAttribute("data-yj-moved","1");}catch(_){}}document.addEventListener("input",mv,true);document.addEventListener("change",mv,true);})();</script></section>
<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">Handsontable, TinyMCE, CKEditor 5, FullCalendar, AG Grid, MUI X and Syncfusion licence keys in closed-source JS/TS</p><p style="margin:0 0 1rem;color:#5b6b7c;font-size:.94rem">AG Grid Enterprise lists at $999 per developer (perpetual, 1 year of updates)</p><a href="https://getreadystack.com/api/buy/cl/polar_cl_28TEyppUEDFxwKYLQ4MLqgJ1M8rgXP2dlGoTk1jC2Jy" 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>
<!--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>
<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||''),src:(function(){try{return (new URLSearchParams(location.search).get('ref')||'').replace(/[^a-z_]/g,'').slice(0,12)}catch(e){return ''}})()})}).catch(function(){});}catch(e){}})();</script>
<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',src:(function(){try{return (new URLSearchParams(location.search).get('ref')||'').replace(/[^a-z_]/g,'').slice(0,12)}catch(e){return ''}})()})}).catch(function(){});}var mo=new MutationObserver(function(){fire();if(sent)mo.disconnect();});mo.observe(o,{childList:true,characterData:true,subtree:true});}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 {"&":"&","<":"<",">":">",'"':"""}[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><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><p style="font:400 13px/1.5 system-ui,sans-serif;color:#6b7680;margin:0 0 14px"><time datetime="2026-09-28">Updated 2026-09-28</time> · ReadyStack</p><script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","dateModified":"2026-09-28","author":{"@type":"Organization","name":"ReadyStack"}}</script><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:0 0 6px;color:#1b1f24">Worked example</h2><p style="font:400 14.5px/1.5 system-ui,sans-serif;margin:0 0 16px;color:#5b6570">Real numbers from this tool, line by line.</p><div class="yj-article"><p><img src="https://getreadystack.com/img/promo/sku358010_result_card.jpg" alt="JS Licence Key Gate: GPL & Eval Keys" loading="lazy" style="max-width:100%;border-radius:6px"></p>
<p>4 GPL and evaluation keys shipped in one widgets.ts: that is what JS Licence Key Gate found in its own test file, and the file is the kind of dashboard bootstrap a front-end lead at a closed-source SaaS company writes every quarter.</p>
<p>Here is the file in outline. A spreadsheet grid from Handsontable, a resource timeline from FullCalendar Premium, a notes field in TinyMCE, a contract editor in CKEditor 5, an AG Grid Enterprise table, an MUI X Pro data grid and a Mapbox map. Every component renders and every test passes.</p>
<p>The four keys that ship:</p>
<p>licenseKey: 'non-commercial-and-evaluation' // Handsontable schedulerLicenseKey: 'GPL-My-Project-Is-Open-Source' // FullCalendar Premium license_key: 'gpl' // TinyMCE 7+ licenseKey: 'GPL' // CKEditor 5</p>
<p>Each one is a declaration. The Handsontable string says the grid is used for evaluation or non-commercial work; Handsontable has been proprietary since 7.0.0. The FullCalendar string says your whole project is released under the GPL. The TinyMCE string says you use TinyMCE 7 under GPLv2+, the licence TinyMCE moved to with 7.0. The CKEditor string says the same for CKEditor 5, which made config.licenseKey a required property in v44.0.0. None of these is true for a closed-source SaaS.</p>
<p>The three warnings in the same file are quieter. AG Grid Enterprise is imported but setLicenseKey is never called in that file. MUI X Pro is imported without LicenseInfo.setLicenseKey. And mapbox-gl is imported: from 2.0.0 it is proprietary, under the Mapbox Terms of Service and billed per map load, while 1.13 was the last BSD-3 release.</p>
<p>Why the usual tools miss it. npm licence checkers read the license field each package declares. That tells you TinyMCE is GPL, which you already know; it does not tell you which key string your code passes. A chatbot asked whether TinyMCE is free answers about the package, not about line 34 of your file. The finding lives in your own source, so the check has to read your own source.</p>
<p>What the extension does. It runs 15 rules over the open file as you type and puts each finding in the Problems panel with the rule id, the line and the fix. The fix is always concrete: load a purchased key from config, pin the last permissive release (handsontable 6.2.2, tinymce 6.8.x), move to a permissive fork (maplibre-gl), or call the vendor's setLicenseKey or registerLicense at app start. On the clean version of the same file, with every key read from a config module, it reports 0 findings.</p>
<p>When it costs you. A wrong key costs nothing on the day you ship. It costs at the moment somebody reads the code with a licence question in mind: a vendor audit, a customer security questionnaire, or acquisition due diligence, where a data room reviewer searches the repository for exactly these strings. The price of the licence you should have held is public: AG Grid Enterprise lists at $999 per developer, perpetual, with one year of updates.</p>
<p>Free and full. The free tier checks one file at a time, in VS Code or in the web page, which runs the same engine.js and rules.json in the browser without uploading anything. That is enough to clean a file before a pull request. The full version scans every file in the workspace in one pass and exports the licence inventory as CSV and Markdown for procurement or a due diligence folder.</p>
<p>It is a technical check, not legal advice: the vendor's licence text decides. But it tells you which lines to take to that text.</p></div><h2 style="font:600 19px/1.3 system-ui,sans-serif;margin:30px 0 10px;color:#1b1f24">15 seconds — what it actually does</h2><video controls muted playsinline preload="none" poster="/img/promo/sku358010_result_card.jpg" style="width:100%;max-width:360px;border-radius:10px;display:block;margin:0 auto"><source src="/media/sku358010_short.mp4" type="video/mp4"></video><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 JS Licence Key Gate actually do?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">It reads a JavaScript or TypeScript file and flags licence key strings that do not fit a closed-source commercial product: the Handsontable evaluation key, FullCalendar GPL and non-commercial keys, TinyMCE license_key 'gpl', CKEditor 5 licenseKey 'GPL', and AG Grid Enterprise, MUI X Pro or Syncfusion imported without a key. It runs 15 rules and gives the line and the fix.</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 JS Licence Key Gate for?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Front-end leads and engineering managers at closed-source SaaS companies, agencies that ship client dashboards built on commercial grids and editors, and teams preparing for a vendor licence audit or acquisition due diligence. It suits anyone whose product imports Handsontable, TinyMCE, CKEditor 5, FullCalendar Premium, AG Grid Enterprise, MUI X Pro or Syncfusion.</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 can't a free npm licence checker find these problems?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Free npm licence checkers read the license field that each package declares in its package.json. The breach here sits in your own source code: a key string such as 'non-commercial-and-evaluation' or license_key 'gpl' passed at runtime. The components render normally with those keys, so tests pass. No dependency scanner reads the value your code passes.</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 does the paid version add?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Free: open any JS or TS file in VS Code, or paste it into the web page, and get every GPL, evaluation or missing commercial key with the line and the fix. The paid version, 29 dollars once per person or team seat, scans every file in the workspace in one pass and exports a CSV and Markdown licence inventory for procurement or due diligence.</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 does fixing a licence finding cost compared with the alternatives?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">The commercial licences themselves are the real cost: AG Grid Enterprise lists at 999 dollars per developer for a perpetual licence with one year of updates. A licence review by counsel during due diligence is billed by the hour. This check runs in the editor as you type and names the line before the code ships.</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 not just ask ChatGPT or another AI chat?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">A general AI chat answers from training data with a cutoff date, cannot read your repository and names no rule version. JS Licence Key Gate: GPL & Eval Keys checks the file you open against 15 rules from a rule set dated 2026-09-28, and points at the exact line with the fix. For a filing, an audit or a client you need that dated result on your own files.</p></details><script type="application/ld+json" data-yj="yj-faq-ld">{"@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [{"@type": "Question", "name": "What does JS Licence Key Gate actually do?", "acceptedAnswer": {"@type": "Answer", "text": "It reads a JavaScript or TypeScript file and flags licence key strings that do not fit a closed-source commercial product: the Handsontable evaluation key, FullCalendar GPL and non-commercial keys, TinyMCE license_key 'gpl', CKEditor 5 licenseKey 'GPL', and AG Grid Enterprise, MUI X Pro or Syncfusion imported without a key. It runs 15 rules and gives the line and the fix."}}, {"@type": "Question", "name": "Who is JS Licence Key Gate for?", "acceptedAnswer": {"@type": "Answer", "text": "Front-end leads and engineering managers at closed-source SaaS companies, agencies that ship client dashboards built on commercial grids and editors, and teams preparing for a vendor licence audit or acquisition due diligence. It suits anyone whose product imports Handsontable, TinyMCE, CKEditor 5, FullCalendar Premium, AG Grid Enterprise, MUI X Pro or Syncfusion."}}, {"@type": "Question", "name": "Why can't a free npm licence checker find these problems?", "acceptedAnswer": {"@type": "Answer", "text": "Free npm licence checkers read the license field that each package declares in its package.json. The breach here sits in your own source code: a key string such as 'non-commercial-and-evaluation' or license_key 'gpl' passed at runtime. The components render normally with those keys, so tests pass. No dependency scanner reads the value your code passes."}}, {"@type": "Question", "name": "What is free and what does the paid version add?", "acceptedAnswer": {"@type": "Answer", "text": "Free: open any JS or TS file in VS Code, or paste it into the web page, and get every GPL, evaluation or missing commercial key with the line and the fix. The paid version, 29 dollars once per person or team seat, scans every file in the workspace in one pass and exports a CSV and Markdown licence inventory for procurement or due diligence."}}, {"@type": "Question", "name": "What does fixing a licence finding cost compared with the alternatives?", "acceptedAnswer": {"@type": "Answer", "text": "The commercial licences themselves are the real cost: AG Grid Enterprise lists at 999 dollars per developer for a perpetual licence with one year of updates. A licence review by counsel during due diligence is billed by the hour. This check runs in the editor as you type and names the line before the code ships."}}, {"@type": "Question", "name": "Why not just ask ChatGPT or another AI chat?", "acceptedAnswer": {"@type": "Answer", "text": "A general AI chat answers from training data with a cutoff date, cannot read your repository and names no rule version. JS Licence Key Gate: GPL & Eval Keys checks the file you open against 15 rules from a rule set dated 2026-09-28, and points at the exact line with the fix. For a filing, an audit or a client you need that dated result on your own files."}}]}</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:358010,slug:"js-licence-key-gate",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.</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/lockfile-due-diligence-lint"><span class="yj-rel-t">Lockfile Due Diligence</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/pekko-migration-gate"><span class="yj-rel-t">Pekko Migration Gate — Akka BSL licence check</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/dotnet-eol-support-gate"><span class="yj-rel-t">.NET EOL & CRA Support Window Gate</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/age-gate-lint"><span class="yj-rel-t">Age Gate Lint — UK Online Safety Act</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/base-image-eol-lint"><span class="yj-rel-t">Base Image EOL Lint - Dockerfile and CI end-of-life check</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/bitnami-image-catalog-gate"><span class="yj-rel-t">Bitnami Image Gate: Compose, Helm, Dockerfile</span><span class="yj-rel-p">$29</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></body>
</html>
|