mirror of
https://github.com/GetOpenScript/OpenScript.git
synced 2026-09-18 09:45:43 +00:00
Add optional script version metadata
This commit is contained in:
@@ -24,6 +24,7 @@ Scripts use a small metadata block followed by ordinary JavaScript. OpenScript s
|
||||
```javascript
|
||||
// ==UserScript==
|
||||
// @name GitHub Repo Stats
|
||||
// @version 1.0.0
|
||||
// @description Logs repository metadata
|
||||
// @match https://github.com/*
|
||||
// @run-at document_idle
|
||||
@@ -41,6 +42,7 @@ console.log(await response.json());
|
||||
| Directive | Description | Required |
|
||||
| :--- | :--- | :--- |
|
||||
| `@name` | Name displayed in the popup | Yes |
|
||||
| `@version` | Version displayed beside the script name | No |
|
||||
| `@match` | Chrome match pattern; repeat for multiple patterns | Yes |
|
||||
| `@description` | Short summary displayed in the popup | No |
|
||||
| `@run-at` | `document_idle`, `document_start`, or `document_end` | No |
|
||||
|
||||
@@ -40,7 +40,10 @@ const init = async () => {
|
||||
await syncScripts(false);
|
||||
const [scripts, secrets] = await Promise.all([getScripts(), getSecrets()]);
|
||||
await garbageCollectScriptStorage(scripts.map(s => s.id));
|
||||
state.scripts = scripts;
|
||||
state.scripts = scripts.map(s => ({
|
||||
...s,
|
||||
version: parseMeta(s.code || '').version,
|
||||
}));
|
||||
state.secrets = secrets;
|
||||
render();
|
||||
};
|
||||
@@ -82,6 +85,7 @@ const saveCurrentScript = async () => {
|
||||
const scriptObj = {
|
||||
id: state.editingId || `script_${Date.now()}`,
|
||||
name: meta.name,
|
||||
version: meta.version,
|
||||
description: meta.description,
|
||||
matches: meta.matches,
|
||||
requires: meta.requires,
|
||||
@@ -204,6 +208,7 @@ const renderScriptList = () => {
|
||||
<span class="font-semibold text-xs text-slate-900 truncate cursor-pointer hover:text-sky-600" data-action="edit" data-id="${s.id}">
|
||||
${s.name}
|
||||
</span>
|
||||
${s.version ? `<span class="text-[9px] font-mono px-1 py-0.2 rounded bg-slate-100 text-slate-500 border border-slate-200 shrink-0">v${s.version}</span>` : ''}
|
||||
</div>
|
||||
<div class="flex items-center gap-1 shrink-0">
|
||||
<button data-action="edit" data-id="${s.id}" class="p-1 hover:bg-slate-100 rounded text-slate-500 hover:text-sky-600 cursor-pointer" title="Edit Script">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Parse OpenScript's deliberately small metadata format.
|
||||
|
||||
const SINGLE_KEYS = new Set(['name', 'description', 'run-at']);
|
||||
const SINGLE_KEYS = new Set(['name', 'version', 'description', 'run-at']);
|
||||
const MULTI_KEYS = new Set(['match', 'require']);
|
||||
|
||||
export const parseMeta = code => {
|
||||
@@ -20,6 +20,7 @@ export const parseMeta = code => {
|
||||
|
||||
return {
|
||||
name: meta.name || 'Untitled Script',
|
||||
version: meta.version || '',
|
||||
description: meta.description || '',
|
||||
matches: meta.match.length ? meta.match : ['*://*/*'],
|
||||
runAt: (meta['run-at'] || 'document_idle').replace('-', '_'),
|
||||
|
||||
@@ -23,6 +23,7 @@ test('parseMeta extracts only OpenScript metadata', () => {
|
||||
|
||||
assert.deepEqual(meta, {
|
||||
name: 'Test Script',
|
||||
version: '2.1.0',
|
||||
description: 'Sample description',
|
||||
matches: ['https://example.com/*'],
|
||||
runAt: 'document_start',
|
||||
@@ -33,6 +34,7 @@ test('parseMeta extracts only OpenScript metadata', () => {
|
||||
test('parseMeta falls back to defaults when fields are missing', () => {
|
||||
const meta = parseMeta('// ==UserScript==\n// ==/UserScript==');
|
||||
assert.equal(meta.name, 'Untitled Script');
|
||||
assert.equal(meta.version, '');
|
||||
assert.equal(meta.description, '');
|
||||
assert.deepEqual(meta.matches, ['*://*/*']);
|
||||
assert.equal(meta.runAt, 'document_idle');
|
||||
@@ -137,6 +139,7 @@ test('getBoilerplate is wrapper-free and minimalist', () => {
|
||||
const template = getBoilerplate('My Script');
|
||||
assert.ok(template.includes('// @name My Script'));
|
||||
assert.ok(template.includes("console.log('Running on', location.hostname);"));
|
||||
for (const legacy of ['@namespace', '@grant', '@version', '@author', '(function'])
|
||||
for (const legacy of ['@namespace', '@grant', '@author', '(function'])
|
||||
assert.ok(!template.includes(legacy));
|
||||
assert.ok(!template.includes('@version'));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user