overlaify 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -46,8 +46,9 @@ npx overlaify publish my-alert.html --new # a separate overlay instead
46
46
  npx overlaify publish my-alert.html --name neon # its address: overlaify.com/<your username>/neon
47
47
  ```
48
48
 
49
- The overlay must pass the spec. It gets its own page at `overlaify.com/<your username>/<name>` (named after
50
- its `<title>` unless you pass `--name`), shows up in My overlays with its OBS URL, and the
49
+ The overlay must pass the spec. It gets its own page at `overlaify.com/<your username>/<name>`. The first publish
50
+ names it after the file (`my-alert.html` → `my-alert`) and lets you change that at the prompt; `--name` sets it
51
+ up front, shows up in My overlays with its OBS URL, and the
51
52
  settings you chose in `overlaify dev` come with it. Which overlay a file was published as is kept in
52
53
  `.overlaify/<name>.publish.json`.
53
54
 
package/lib/publish.js CHANGED
@@ -148,6 +148,13 @@ const readJsonFile = (f) => {
148
148
  try { return JSON.parse(readFileSync(f, 'utf8')); } catch { return null; }
149
149
  };
150
150
 
151
+ const NAME_RE = /^[a-z0-9](?:[a-z0-9-]{0,58}[a-z0-9])?$/;
152
+ const NAME_RULE = 'must be 1–60 lowercase letters, digits or dashes, not at the start or end.';
153
+
154
+ // The file name as an overlay name: my_Alert v2.html → my-alert-v2. Empty when nothing usable is left.
155
+ const nameOf = (file) =>
156
+ basename(file).replace(/\.html?$/i, '').toLowerCase().replace(/[^a-z0-9]+/g, '-').slice(0, 60).replace(/^-+|-+$/g, '');
157
+
151
158
  const titleOf = (html, file) =>
152
159
  (/<title[^>]*>([^<]*)<\/title>/i.exec(html)?.[1] || '').replace(/\s+/g, ' ').trim() || basename(file).replace(/\.html?$/i, '');
153
160
 
@@ -155,16 +162,15 @@ const titleOf = (html, file) =>
155
162
  * overlaify publish [file] [--public | --private] [--name n] [--title t] [--kind k] [--new] [--site url]
156
163
  * Uploads the overlay to My overlays. The first publish of a file asks public or private; publishing it
157
164
  * again adds a new version to the same overlay (its OBS URL changes to the new version's) unless --new.
158
- * `name` is its address, overlaify.com/<handle>/<name>; a new overlay is otherwise named after its title.
165
+ * `name` is its address, overlaify.com/<handle>/<name>; a new overlay is otherwise named after its file
166
+ * (asked at a terminal, with the file name as the default), or after its title when the file name has no usable letters.
159
167
  */
160
168
  export async function publish(file, { site, visibility, name, title, kind, fresh, log = console.log } = {}) {
161
169
  site = siteUrl(site);
162
170
  file = resolve(file);
163
171
  if (!existsSync(file)) throw new Error(`No such file: ${file}`);
164
172
  if (kind && !KINDS.includes(kind)) throw new Error(`--kind must be one of ${KINDS.join(', ')}.`);
165
- if (name != null && !/^[a-z0-9](?:[a-z0-9-]{0,58}[a-z0-9])?$/.test(name)) {
166
- throw new Error('--name must be 1–60 lowercase letters, digits or dashes, not at the start or end.');
167
- }
173
+ if (name != null && !NAME_RE.test(name)) throw new Error(`--name ${NAME_RULE}`);
168
174
  if (!tokenFor(site)) throw new Error(`Not logged in to ${site}. Run: overlaify login${site === DEFAULT_SITE ? '' : ` --site ${site}`}`);
169
175
 
170
176
  const html = readFileSync(file, 'utf8');
@@ -183,6 +189,17 @@ export async function publish(file, { site, visibility, name, title, kind, fresh
183
189
  visibility = a === '2' || a.startsWith('pub') ? 'public' : a === '' || a === '1' || a.startsWith('pri') ? 'private' : null;
184
190
  if (!visibility) throw new Error('Publishing cancelled.');
185
191
  }
192
+ // A new overlay is named after its file unless --name says otherwise; at a terminal the name can be changed.
193
+ if (name == null && !previous) {
194
+ const fallback = nameOf(file);
195
+ if (process.stdin.isTTY) {
196
+ const a = (await ask(`Name, its address overlaify.com/<you>/<name>${fallback ? ` [${fallback}]` : ''}: `)).toLowerCase();
197
+ name = a || fallback || undefined;
198
+ if (name && !NAME_RE.test(name)) throw new Error(`The name ${NAME_RULE}`);
199
+ } else {
200
+ name = fallback || undefined;
201
+ }
202
+ }
186
203
 
187
204
  const body = { html, title: title || titleOf(html, file), name, kind, visibility, config: readJsonFile(stateFile(file, '.json')) || undefined };
188
205
  let out;
package/package.json CHANGED
@@ -1,16 +1,37 @@
1
1
  {
2
2
  "name": "overlaify",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Build Twitch/OBS overlays that follow the Overlaify Overlay Spec: start from a template, validate, preview with simulated events and control them live.",
5
5
  "type": "module",
6
- "bin": { "overlaify": "bin/overlaify.js" },
7
- "files": ["bin", "lib", "assets", "skill"],
8
- "engines": { "node": ">=18" },
6
+ "bin": {
7
+ "overlaify": "bin/overlaify.js"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "lib",
12
+ "assets",
13
+ "skill"
14
+ ],
15
+ "engines": {
16
+ "node": ">=18"
17
+ },
9
18
  "scripts": {
10
19
  "sync": "node scripts/sync.mjs"
11
20
  },
12
- "keywords": ["twitch", "obs", "overlay", "stream", "alerts", "browser-source", "claude", "skill"],
21
+ "keywords": [
22
+ "twitch",
23
+ "obs",
24
+ "overlay",
25
+ "stream",
26
+ "alerts",
27
+ "browser-source",
28
+ "claude",
29
+ "skill"
30
+ ],
13
31
  "homepage": "https://www.overlaify.com",
14
- "repository": { "type": "git", "url": "git+https://github.com/overlaify/overlaify.git" },
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "git+https://github.com/overlaify/overlaify.git"
35
+ },
15
36
  "license": "MIT"
16
37
  }
package/skill/SKILL.md CHANGED
@@ -30,7 +30,7 @@ The full rules are in `references/overlay-spec.md`. Read it before writing your
30
30
  when the file is saved, and the action keys reach it live.
31
31
  Tell the user to set their Twitch channel in the dev page's settings so real chat and events arrive.
32
32
  5. **Publish (only when the user asks).** `npx overlaify publish <file>.html --private` or `--public` puts it
33
- on overlaify.com at `/<their username>/<name>` with a hosted OBS URL (`--name` sets the name). Ask the user which one they want; never pick for
33
+ on overlaify.com at `/<their username>/<name>` with a hosted OBS URL (named after the file, e.g. `my-alert.html` → `my-alert`; `--name` sets another). Ask the user which one they want; never pick for
34
34
  them. Private: only they can open it on the site, but the OBS URL still works. Public: anyone with a link
35
35
  can open and remix it, and it can be picked for the Overlaify Library. If it says they're not logged in,
36
36
  ask them to run `npx overlaify login` (it opens a browser to approve). Publishing the same file again