extension-create 4.0.13 → 4.0.14-canary.1784515910.7d7da9cc

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.
@@ -12,6 +12,8 @@ export declare function writingTypeDefinitionsError(error: any): string;
12
12
  export declare function installingFromTemplate(projectName: string, templateName: string): string;
13
13
  export declare function installingFromTemplateError(projectName: string, template: string, error: any): string;
14
14
  export declare function templateFetchTimedOut(templateName: string, ms: number): string;
15
+ export declare function templateNotFoundInCatalog(templateName: string, error?: any): string;
16
+ export declare function templateDownloadFailed(templateName: string, error: any): string;
15
17
  export declare function initializingGitForRepository(projectName: string): string;
16
18
  export declare function initializingGitSkipped(projectName: string, reason: string): string;
17
19
  export declare function installingDependencies(): string;
package/dist/module.cjs CHANGED
@@ -129,6 +129,12 @@ function installingFromTemplateError(projectName, template, error) {
129
129
  function templateFetchTimedOut(templateName, ms) {
130
130
  return `${external_pintor_default().red('Error')} Timed out after ${external_pintor_default().yellow(`${Math.round(ms / 1000)}s`)} fetching template ${external_pintor_default().yellow(templateName)}.\n${external_pintor_default().red('Next step: check your network, or set EXTENSION_CREATE_TIMEOUT_MS to allow more time.')}`;
131
131
  }
132
+ function templateNotFoundInCatalog(templateName, error) {
133
+ return `${external_pintor_default().red('Error')} Template ${external_pintor_default().yellow(templateName)} is not in the extension-js/examples catalog.\n` + (error ? `${external_pintor_default().red(String(error))}\n` : '') + `${external_pintor_default().red('Next step: run')} ${external_pintor_default().yellow('extension create --help')} ` + `${external_pintor_default().red('to list valid template names, or pass a GitHub URL.')}`;
134
+ }
135
+ function templateDownloadFailed(templateName, error) {
136
+ return `${external_pintor_default().red('Error')} Couldn't download template ${external_pintor_default().yellow(templateName)} from ${external_pintor_default().yellow('github.com/extension-js/examples')}.\n${external_pintor_default().red(String(error && error.message || error))}\n${external_pintor_default().red('Next step: check your network (or GitHub rate limits) and try again; set EXTENSION_CREATE_TIMEOUT_MS to allow more time.')}`;
137
+ }
132
138
  function initializingGitForRepository(projectName) {
133
139
  return `${statusPrefix} Initializing git repository for ${external_pintor_default().blue(projectName)}...`;
134
140
  }
@@ -313,10 +319,88 @@ const external_adm_zip_namespaceObject = require("adm-zip");
313
319
  var external_adm_zip_default = /*#__PURE__*/ __webpack_require__.n(external_adm_zip_namespaceObject);
314
320
  const external_go_git_it_namespaceObject = require("go-git-it");
315
321
  var external_go_git_it_default = /*#__PURE__*/ __webpack_require__.n(external_go_git_it_namespaceObject);
322
+ function _define_property(obj, key, value) {
323
+ if (key in obj) Object.defineProperty(obj, key, {
324
+ value: value,
325
+ enumerable: true,
326
+ configurable: true,
327
+ writable: true
328
+ });
329
+ else obj[key] = value;
330
+ return obj;
331
+ }
316
332
  const NETWORK_TIMEOUT_MS = (()=>{
317
333
  const raw = parseInt(String(process.env.EXTENSION_CREATE_TIMEOUT_MS || ''), 10);
318
334
  return Number.isFinite(raw) && raw > 0 ? raw : 60000;
319
335
  })();
336
+ const EXAMPLES_REF = process.env.EXTENSION_CREATE_TEMPLATE_REF || 'main';
337
+ class TemplateNotFoundError extends Error {
338
+ constructor(templateName, cause){
339
+ super(`template not found in catalog: ${templateName}`), _define_property(this, "templateName", void 0);
340
+ this.name = 'TemplateNotFoundError';
341
+ this.templateName = templateName;
342
+ if (cause) this.cause = cause;
343
+ }
344
+ }
345
+ class TemplateDownloadError extends Error {
346
+ constructor(templateName, cause){
347
+ const msg = cause?.message ?? String(cause);
348
+ super(msg), _define_property(this, "templateName", void 0);
349
+ this.name = 'TemplateDownloadError';
350
+ this.templateName = templateName;
351
+ this.cause = cause;
352
+ }
353
+ }
354
+ const sleep = (ms)=>new Promise((r)=>setTimeout(r, ms));
355
+ async function downloadArchive(url, timeoutMs, attempts = 2) {
356
+ let lastError;
357
+ for(let attempt = 1; attempt <= attempts; attempt++)try {
358
+ const { data } = await external_axios_default().get(url, {
359
+ responseType: 'arraybuffer',
360
+ maxRedirects: 5,
361
+ timeout: timeoutMs,
362
+ headers: {
363
+ 'User-Agent': 'extension-create'
364
+ }
365
+ });
366
+ return Buffer.from(data);
367
+ } catch (error) {
368
+ lastError = error;
369
+ if (attempt < attempts) await sleep(400 * attempt);
370
+ }
371
+ throw lastError;
372
+ }
373
+ async function extractExamplesTemplateFromZip(zipBuffer, templateName, projectPath) {
374
+ const zip = new (external_adm_zip_default())(zipBuffer);
375
+ const entries = zip.getEntries();
376
+ if (!entries.length) throw new TemplateNotFoundError(templateName, new Error('empty archive'));
377
+ const archiveRoot = entries[0].entryName.split('/')[0];
378
+ const wanted = `${archiveRoot}/examples/${templateName}/`;
379
+ const files = entries.filter((e)=>!e.isDirectory && e.entryName.startsWith(wanted));
380
+ if (!files.length) throw new TemplateNotFoundError(templateName);
381
+ let written = 0;
382
+ for (const entry of files){
383
+ const rel = entry.entryName.slice(wanted.length);
384
+ if (!rel) continue;
385
+ const dest = external_path_namespaceObject.join(projectPath, rel);
386
+ await promises_namespaceObject.mkdir(external_path_namespaceObject.dirname(dest), {
387
+ recursive: true
388
+ });
389
+ await promises_namespaceObject.writeFile(dest, entry.getData());
390
+ written++;
391
+ }
392
+ return written;
393
+ }
394
+ async function importFromExamplesCatalog(templateName, projectPath) {
395
+ const url = `https://codeload.github.com/extension-js/examples/zip/refs/heads/${EXAMPLES_REF}`;
396
+ let buffer;
397
+ try {
398
+ buffer = await downloadArchive(url, NETWORK_TIMEOUT_MS);
399
+ } catch (error) {
400
+ throw new TemplateDownloadError(templateName, error);
401
+ }
402
+ await extractExamplesTemplateFromZip(buffer, templateName, projectPath);
403
+ }
320
404
  function isAuthorOrDevMode() {
321
405
  return 'development' === process.env.EXTENSION_ENV || 'true' === process.env.EXTENSION_AUTHOR_MODE;
322
406
  }
@@ -384,10 +468,8 @@ async function getZipSourcePath(tempPath, templateUrl) {
384
468
  }
385
469
  async function importExternalTemplate(projectPath, projectName, template, logger) {
386
470
  const templateName = external_path_namespaceObject.basename(template);
387
- const examplesUrl = 'https://github.com/extension-js/examples/tree/main/examples';
388
471
  const resolvedTemplate = 'init' === templateName ? "javascript" : template;
389
472
  const resolvedTemplateName = 'init' === templateName ? "javascript" : templateName;
390
- const templateUrl = `${examplesUrl}/${resolvedTemplate}`;
391
473
  const isHttp = /^https?:\/\//i.test(template);
392
474
  const isGithub = /^https?:\/\/github\.com\//i.test(template);
393
475
  try {
@@ -408,7 +490,22 @@ async function importExternalTemplate(projectPath, projectName, template, logger
408
490
  recursive: true
409
491
  });
410
492
  const runGoGitIt = async (templatePath, destination)=>{
411
- await withTimeout(withSuppressedOutput(async ()=>external_go_git_it_default()(templatePath, destination, installingFromTemplate(projectName, templateName))), NETWORK_TIMEOUT_MS, ()=>new Error(templateFetchTimedOut(templateName, NETWORK_TIMEOUT_MS)));
493
+ const gitEnvKeys = {
494
+ GIT_TERMINAL_PROMPT: '0',
495
+ GIT_ASKPASS: '',
496
+ GCM_INTERACTIVE: 'never'
497
+ };
498
+ const savedEnv = {};
499
+ for (const [k, v] of Object.entries(gitEnvKeys)){
500
+ savedEnv[k] = process.env[k];
501
+ process.env[k] = v;
502
+ }
503
+ try {
504
+ await withTimeout(withSuppressedOutput(async ()=>external_go_git_it_default()(templatePath, destination, installingFromTemplate(projectName, templateName))), NETWORK_TIMEOUT_MS, ()=>new Error(templateFetchTimedOut(templateName, NETWORK_TIMEOUT_MS)));
505
+ } finally{
506
+ for (const [k, v] of Object.entries(savedEnv))if (void 0 === v) delete process.env[k];
507
+ else process.env[k] = v;
508
+ }
412
509
  };
413
510
  if (isGithub) {
414
511
  await runGoGitIt(template, tempPath);
@@ -431,18 +528,20 @@ async function importExternalTemplate(projectPath, projectName, template, logger
431
528
  zip.extractAllTo(tempPath, true);
432
529
  const sourcePath = await getZipSourcePath(tempPath, template);
433
530
  await moveDirectoryContents(sourcePath, projectPath);
434
- } else {
435
- await runGoGitIt(templateUrl, tempPath);
436
- const srcPath = external_path_namespaceObject.join(tempPath, resolvedTemplateName);
437
- await moveDirectoryContents(srcPath, projectPath);
438
- }
531
+ } else await importFromExamplesCatalog(resolvedTemplateName, projectPath);
439
532
  await removeTemplateScaffoldingFiles(projectPath);
440
533
  await promises_namespaceObject.rm(tempRoot, {
441
534
  recursive: true,
442
535
  force: true
443
536
  });
444
537
  } catch (error) {
445
- logger.error(installingFromTemplateError(projectName, templateName, error));
538
+ if (error instanceof TemplateNotFoundError) logger.error(templateNotFoundInCatalog(templateName, error.cause));
539
+ else if (error instanceof TemplateDownloadError) logger.error(templateDownloadFailed(templateName, error));
540
+ else logger.error(installingFromTemplateError(projectName, templateName, error));
541
+ await promises_namespaceObject.rm(projectPath, {
542
+ recursive: true,
543
+ force: true
544
+ }).catch(()=>{});
446
545
  throw error;
447
546
  }
448
547
  }
@@ -497,9 +596,22 @@ const ML_DEP_TRIGGERS = [
497
596
  '@xenova/transformers'
498
597
  ];
499
598
  const uniq = (values)=>Array.from(new Set(values.filter(Boolean)));
599
+ function engineVersionOverrideFromEnv() {
600
+ const raw = (process.env.EXTENSION_CREATE_ENGINE_VERSION || process.env.EXTENSION_MCP_CLI_VERSION || '').trim();
601
+ return raw || void 0;
602
+ }
603
+ function ownCreatePackageVersion() {
604
+ try {
605
+ const pkg = JSON.parse((0, external_fs_namespaceObject.readFileSync)(external_path_namespaceObject.join(__dirname, '..', 'package.json'), 'utf8'));
606
+ return 'string' == typeof pkg.version && pkg.version ? pkg.version : void 0;
607
+ } catch {
608
+ return;
609
+ }
610
+ }
500
611
  function resolveExtensionDevDependencyVersion(cliVersion) {
501
- if (!cliVersion) return 'latest';
502
- return cliVersion.includes('-') ? cliVersion : `^${cliVersion}`;
612
+ const resolved = cliVersion || engineVersionOverrideFromEnv() || ownCreatePackageVersion();
613
+ if (!resolved) return 'latest';
614
+ return resolved.includes('-') ? resolved : `^${resolved}`;
503
615
  }
504
616
  async function overridePackageJson(projectPath, projectName, { template = "javascript", cliVersion }, logger) {
505
617
  const extensionBinary = await resolveExtensionBinary();
@@ -1,3 +1,12 @@
1
+ export declare class TemplateNotFoundError extends Error {
2
+ readonly templateName: string;
3
+ constructor(templateName: string, cause?: unknown);
4
+ }
5
+ export declare class TemplateDownloadError extends Error {
6
+ readonly templateName: string;
7
+ constructor(templateName: string, cause: unknown);
8
+ }
9
+ export declare function extractExamplesTemplateFromZip(zipBuffer: Buffer, templateName: string, projectPath: string): Promise<number>;
1
10
  export declare const TEMPLATE_SCAFFOLDING_FILES: string[];
2
11
  export declare function removeTemplateScaffoldingFiles(projectPath: string): Promise<void>;
3
12
  export declare function importExternalTemplate(projectPath: string, projectName: string, template: string, logger: {
package/package.json CHANGED
@@ -25,7 +25,7 @@
25
25
  "templates"
26
26
  ],
27
27
  "name": "extension-create",
28
- "version": "4.0.13",
28
+ "version": "4.0.14-canary.1784515910.7d7da9cc",
29
29
  "description": "The standalone extension creation engine for Extension.js",
30
30
  "author": {
31
31
  "name": "Cezar Augusto",
@@ -1,41 +0,0 @@
1
- <a href="https://extension.js.org" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/Powered%20by%20%7C%20Extension.js-0971fe" alt="Powered by Extension.js" align="right" /></a>
2
-
3
- # test-template-javascript
4
-
5
- > JavaScript-based extension with a sidebar panel. Adds a sidebar with a simple page.
6
-
7
-
8
- ![screenshot](./public/screenshot.png)
9
- ## Commands
10
-
11
- ### dev
12
-
13
- Run the extension in development mode. Target a browser with `--browser`:
14
-
15
- ```bash
16
- pnpm run dev
17
- pnpm run dev -- --browser=firefox
18
- pnpm run dev -- --browser=edge
19
- ```
20
-
21
- ### build
22
-
23
- Build for production. Convenience scripts target each browser:
24
-
25
- ```bash
26
- pnpm run build # Chrome (default)
27
- pnpm run build:firefox
28
- pnpm run build:edge
29
- ```
30
-
31
- ### preview
32
-
33
- Preview the production build in the browser:
34
-
35
- ```bash
36
- pnpm run preview
37
- ```
38
-
39
- ## Learn more
40
-
41
- [Extension.js docs](https://extension.js.org).
@@ -1,19 +0,0 @@
1
- /** @type {import('extension').FileConfig} */
2
- // Extension.js uses a fresh profile on every run.
3
- // Prefer that default? Remove the profile config below.
4
- const profile = (name) => `./dist/extension-profile-${name}`
5
- const ciFlags = process.env.CI ? ['--no-sandbox', '--disable-gpu'] : []
6
-
7
- export default {
8
- browser: {
9
- chrome: {profile: profile('chrome'), browserFlags: ciFlags},
10
- chromium: {profile: profile('chromium'), browserFlags: ciFlags},
11
- edge: {profile: profile('edge'), browserFlags: ciFlags},
12
- firefox: {profile: profile('firefox')},
13
- 'chromium-based': {
14
- profile: profile('chromium-based'),
15
- browserFlags: ciFlags
16
- },
17
- 'gecko-based': {profile: profile('gecko-based')}
18
- }
19
- }
@@ -1,32 +0,0 @@
1
- {
2
- "private": true,
3
- "name": "test-template-javascript",
4
- "description": "JavaScript-based extension with a sidebar panel. Adds a sidebar with a simple page.",
5
- "version": "1.0.0",
6
- "license": "MIT",
7
- "type": "module",
8
- "author": {
9
- "name": "Your Name",
10
- "email": "your@email.com",
11
- "url": "https://yourwebsite.com"
12
- },
13
- "scripts": {
14
- "dev": "extension dev",
15
- "start": "extension start",
16
- "build": "extension build",
17
- "preview": "extension preview",
18
- "build:chrome": "extension build --browser chrome",
19
- "build:firefox": "extension build --browser firefox",
20
- "build:edge": "extension build --browser edge"
21
- },
22
- "dependencies": {},
23
- "devDependencies": {
24
- "extension": "latest"
25
- },
26
- "packageManager": "pnpm@10.28.0",
27
- "pnpm": {
28
- "ignoredBuiltDependencies": [
29
- "less"
30
- ]
31
- }
32
- }
@@ -1,44 +0,0 @@
1
- console.log(
2
- '[From the background context] Hello from the background worker/script!'
3
- )
4
-
5
- const isFirefoxLike =
6
- import.meta.env.EXTENSION_PUBLIC_BROWSER === 'firefox' ||
7
- import.meta.env.EXTENSION_PUBLIC_BROWSER === 'gecko-based'
8
-
9
- if (isFirefoxLike) {
10
- browser.browserAction.onClicked.addListener(() => {
11
- browser.sidebarAction.open()
12
- })
13
-
14
- browser.runtime.onMessage.addListener((message) => {
15
- if (!message || message.type !== 'openSidebar') return
16
-
17
- browser.sidebarAction.open()
18
- })
19
- }
20
-
21
- if (!isFirefoxLike) {
22
- // setPanelBehavior only affects FUTURE action clicks — registering it
23
- // inside onClicked would swallow the first toolbar click.
24
- chrome.sidePanel.setPanelBehavior({openPanelOnActionClick: true})
25
- }
26
-
27
- chrome.runtime.onMessage.addListener((message) => {
28
- if (!message || message.type !== 'openSidebar') return
29
-
30
- chrome.sidePanel.setPanelBehavior({openPanelOnActionClick: true})
31
-
32
- if (!chrome.sidePanel.open) return
33
-
34
- chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
35
- const activeTabId = tabs && tabs[0] && tabs[0].id
36
- if (!activeTabId) return
37
-
38
- try {
39
- chrome.sidePanel.open({tabId: activeTabId})
40
- } catch (error) {
41
- console.error(error)
42
- }
43
- })
44
- })
@@ -1,41 +0,0 @@
1
- import logo from '../images/icon.png'
2
-
3
- export default function createContentApp() {
4
- const container = document.createElement('div')
5
- container.className = 'content_script'
6
-
7
- const pill = document.createElement('button')
8
- pill.type = 'button'
9
- pill.className = 'content_pill'
10
- pill.setAttribute('aria-label', 'Open sidebar')
11
- pill.addEventListener('click', () => {
12
- try {
13
- if (
14
- import.meta.env.EXTENSION_PUBLIC_BROWSER === 'firefox' ||
15
- import.meta.env.EXTENSION_PUBLIC_BROWSER === 'gecko-based'
16
- ) {
17
- browser.runtime.sendMessage({type: 'openSidebar'})
18
- } else {
19
- chrome.runtime.sendMessage({type: 'openSidebar'})
20
- }
21
- } catch (error) {
22
- console.error(error)
23
- }
24
- })
25
-
26
- const img = document.createElement('img')
27
- img.className = 'content_pill_logo'
28
- img.src = logo
29
- img.alt = ''
30
- img.setAttribute('aria-hidden', 'true')
31
-
32
- const text = document.createElement('span')
33
- text.className = 'content_pill_text'
34
- text.textContent = 'Open sidebar'
35
-
36
- pill.appendChild(img)
37
- pill.appendChild(text)
38
- container.appendChild(pill)
39
-
40
- return container
41
- }
@@ -1,44 +0,0 @@
1
- import createContentApp from './ContentApp.js'
2
- import './styles.css'
3
-
4
- console.log('[From the page context] Hello from content_scripts!')
5
-
6
- /**
7
- * Extension.js content_script entrypoint. The framework calls this on
8
- * injection and calls the returned function on HMR/teardown to clean up.
9
- * Do not invoke it yourself.
10
- */
11
- export default function initial() {
12
- const rootDiv = document.createElement('div')
13
- rootDiv.setAttribute('data-extension-root', 'true')
14
- // Isolate the host from page styles (e.g. example.com ships div{opacity:.8},
15
- // which would otherwise fade the whole widget): the shadow DOM only protects
16
- // descendants; the host element itself still takes page CSS.
17
- rootDiv.style.cssText = 'all: initial !important'
18
- document.body.appendChild(rootDiv)
19
-
20
- // Injecting content_scripts inside a shadow dom
21
- // prevents conflicts with the host page's styles.
22
- // This way, styles from the extension won't leak into the host page.
23
- const shadowRoot = rootDiv.attachShadow({mode: 'open'})
24
-
25
- const styleElement = document.createElement('style')
26
- shadowRoot.appendChild(styleElement)
27
-
28
- fetchCSS().then((response) => (styleElement.textContent = response))
29
-
30
- // Render ContentApp inside shadow root
31
- const container = createContentApp()
32
- shadowRoot.appendChild(container)
33
-
34
- return () => {
35
- rootDiv.remove()
36
- }
37
- }
38
-
39
- async function fetchCSS() {
40
- const cssUrl = new URL('./styles.css', import.meta.url)
41
- const response = await fetch(cssUrl)
42
- const text = await response.text()
43
- return response.ok ? text : Promise.reject(text)
44
- }
@@ -1,45 +0,0 @@
1
- .content_script {
2
- position: absolute;
3
- right: 0.75rem;
4
- bottom: 0.75rem;
5
- z-index: 9999;
6
- }
7
-
8
- .content_pill {
9
- -webkit-font-smoothing: antialiased;
10
- -moz-osx-font-smoothing: grayscale;
11
- appearance: none;
12
- border: none;
13
- outline: none;
14
- cursor: pointer;
15
- display: inline-flex;
16
- align-items: center;
17
- gap: 0.5rem;
18
- background: var(--sidebar-bg, #0a0c10);
19
- color: var(--sidebar-text, #c9c9c9);
20
- padding: 0.5rem 1rem 0.5rem 0.5rem;
21
- border-radius: 9999px;
22
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.25);
23
- }
24
-
25
- .content_pill:hover {
26
- background: #11151c;
27
- }
28
-
29
- .content_pill_logo {
30
- height: 1.5rem;
31
- border-radius: 9999px;
32
- background: rgba(255, 255, 255, 0.08);
33
- object-fit: contain;
34
- aspect-ratio: 1 / 1;
35
- padding: 0.125rem;
36
- }
37
-
38
- .content_pill_text {
39
- font-size: 0.85rem;
40
- font-weight: 600;
41
- line-height: 1;
42
- font-family:
43
- -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
44
- Arial, "Noto Sans", sans-serif;
45
- }
@@ -1,63 +0,0 @@
1
- {
2
- "$schema": "https://json.schemastore.org/chrome-manifest.json",
3
- "chromium:manifest_version": 3,
4
- "firefox:manifest_version": 2,
5
- "version": "1.0.0",
6
- "name": "test-template-javascript",
7
- "description": "JavaScript-based extension with a sidebar panel. Adds a sidebar with a simple page.",
8
- "icons": {
9
- "16": "images/icon.png",
10
- "32": "images/icon.png",
11
- "48": "images/icon.png",
12
- "64": "images/icon.png",
13
- "128": "images/icon.png"
14
- },
15
- "chromium:action": {
16
- "default_icon": {
17
- "16": "images/icon.png",
18
- "32": "images/icon.png",
19
- "48": "images/icon.png",
20
- "64": "images/icon.png",
21
- "128": "images/icon.png"
22
- },
23
- "default_title": "Open Side Panel"
24
- },
25
- "firefox:browser_action": {
26
- "default_icon": {
27
- "16": "images/icon.png",
28
- "32": "images/icon.png",
29
- "48": "images/icon.png",
30
- "64": "images/icon.png",
31
- "128": "images/icon.png"
32
- },
33
- "default_title": "Open Side Panel"
34
- },
35
- "chromium:side_panel": {
36
- "default_path": "sidebar/index.html",
37
- "default_title": "Side Panel Content"
38
- },
39
- "firefox:sidebar_action": {
40
- "default_panel": "sidebar/index.html",
41
- "default_title": "Side Panel Content"
42
- },
43
- "chromium:permissions": [
44
- "sidePanel"
45
- ],
46
- "background": {
47
- "chromium:service_worker": "background.js",
48
- "firefox:scripts": [
49
- "background.js"
50
- ]
51
- },
52
- "content_scripts": [
53
- {
54
- "matches": [
55
- "<all_urls>"
56
- ],
57
- "js": [
58
- "content/scripts.js"
59
- ]
60
- }
61
- ],
62
- "author": "Your Name"
63
- }
@@ -1,28 +0,0 @@
1
- import './styles.css'
2
- import javascriptLogo from '../images/icon.png'
3
-
4
- function SidebarApp() {
5
- const root = document.getElementById('root')
6
- if (!root) return
7
-
8
- root.innerHTML = `
9
- <div class="sidebar_app">
10
- <img
11
- class="sidebar_logo"
12
- src="${javascriptLogo}"
13
- alt="The JavaScript logo"
14
- />
15
- <h1 class="sidebar_title">Sidebar Panel</h1>
16
- <p class="sidebar_description">
17
- Learn more in the
18
- <a
19
- href="https://extension.js.org"
20
- target="_blank" rel="noopener noreferrer"
21
- >Extension.js docs</a>
22
- .
23
- </p>
24
- </div>
25
- `
26
- }
27
-
28
- SidebarApp()
@@ -1,13 +0,0 @@
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>JavaScript Sidebar</title>
7
- </head>
8
- <body>
9
- <noscript>You need to enable JavaScript to run this extension.</noscript>
10
- <div id="root"></div>
11
- </body>
12
- <script src="./scripts.js"></script>
13
- </html>
@@ -1,4 +0,0 @@
1
- import './SidebarApp.js'
2
- import './styles.css'
3
-
4
- console.log('[From the sidebar page context] Hello regular page!')
@@ -1,60 +0,0 @@
1
- /* @import 'sakura.css'; */
2
-
3
- :root {
4
- --sidebar-margin: 1rem;
5
- --sidebar-bg: #0a0c10;
6
- --sidebar-text: #c9c9c9;
7
- --sidebar-link: #e5e7eb;
8
- --sidebar-border: #c9c9c9;
9
- }
10
-
11
- body {
12
- background-color: var(--sidebar-bg);
13
- color: var(--sidebar-text);
14
- height: 100vh;
15
- margin: var(--sidebar-margin);
16
- border-radius: 6px;
17
- display: flex;
18
- justify-content: center;
19
- align-items: center;
20
- overflow: hidden;
21
- }
22
-
23
- .sidebar_app {
24
- display: flex;
25
- flex-direction: column;
26
- align-items: center;
27
- padding: 0 1rem;
28
- text-align: center;
29
- max-height: 100vh;
30
- overflow-y: auto;
31
- }
32
-
33
- .sidebar_logo {
34
- width: 72px;
35
- margin: 0 auto 1rem;
36
- }
37
-
38
- .sidebar_title {
39
- font-size: 1.85em;
40
- line-height: 1.1;
41
- font-family:
42
- -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
43
- Arial, "Noto Sans", sans-serif;
44
- font-weight: 700;
45
- margin: 0;
46
- text-align: center;
47
- }
48
-
49
- .sidebar_description {
50
- font-size: small;
51
- margin: 0.5rem 0 0;
52
- text-align: center;
53
- }
54
-
55
- .sidebar_description a {
56
- text-decoration: none;
57
- border-bottom: 2px solid var(--sidebar-border);
58
- color: var(--sidebar-link);
59
- margin: 0;
60
- }