Full Code of larscom/ng-chrome-extension for AI

master 709a1dc3283c cached
12 files
15.0 KB
4.2k tokens
22 symbols
1 requests
Download .txt
Repository: larscom/ng-chrome-extension
Branch: master
Commit: 709a1dc3283c
Files: 12
Total size: 15.0 KB

Directory structure:
gitextract_1ulcxw8j/

├── .github/
│   └── workflows/
│       └── workflow.yml
├── .gitignore
├── .npmrc
├── LICENSE
├── README.md
├── package.json
├── rollup.config.js
├── src/
│   ├── logger.ts
│   ├── main.ts
│   ├── spinner.ts
│   └── version.ts
└── tsconfig.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/workflows/workflow.yml
================================================
name: workflow

on:
  push:
    tags:
      - '*.*.*'
    branches:
      - '**'
  pull_request:
    branches:
      - master

permissions:
  id-token: write
  contents: read

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      TZ: Europe/Amsterdam
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: 24
          registry-url: https://registry.npmjs.org/
      - run: |
          npm ci --ignore-scripts --legacy-peer-deps
          npm run build

  publish:
    if: startsWith(github.ref, 'refs/tags/')
    needs: [build]
    runs-on: ubuntu-latest
    env:
      TZ: Europe/Amsterdam
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version: 24
          registry-url: https://registry.npmjs.org/ 
      - run: |
          version=${{ github.ref_name }}
          sed -i "s/{{PLACEHOLDER_VERSION}}/${version}/" ./src/version.ts
          cat ./src/version.ts
      - run: |
          npm ci --ignore-scripts --legacy-peer-deps
          npm run build
      - run: |
          cp README.md ./dist
          cp LICENSE ./dist
          cp package.json ./dist
          cd dist && npm publish


================================================
FILE: .gitignore
================================================
# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore

# Logs

logs
_.log
npm-debug.log_
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Caches

.cache

# Diagnostic reports (https://nodejs.org/api/report.html)

report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json

# Runtime data

pids
_.pid
_.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover

lib-cov

# Coverage directory used by tools like istanbul

coverage
*.lcov

# nyc test coverage

.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)

.grunt

# Bower dependency directory (https://bower.io/)

bower_components

# node-waf configuration

.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)

build/Release

# Dependency directories

node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)

web_modules/

# TypeScript cache

*.tsbuildinfo

# Optional npm cache directory

.npm

# Optional eslint cache

.eslintcache

# Optional stylelint cache

.stylelintcache

# Microbundle cache

.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history

.node_repl_history

# Output of 'npm pack'

*.tgz

# Yarn Integrity file

.yarn-integrity

# dotenv environment variable files

.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# parcel-bundler cache (https://parceljs.org/)

.parcel-cache

# Next.js build output

.next
out

# Nuxt.js build / generate output

.nuxt
dist

# Gatsby files

# Comment in the public line in if your project uses Gatsby and not Next.js

# https://nextjs.org/blog/next-9-1#public-directory-support

# public

# vuepress build output

.vuepress/dist

# vuepress v2.x temp and cache directory

.temp

# Docusaurus cache and generated files

.docusaurus

# Serverless directories

.serverless/

# FuseBox cache

.fusebox/

# DynamoDB Local files

.dynamodb/

# TernJS port file

.tern-port

# Stores VSCode versions used for testing VSCode extensions

.vscode-test

# yarn v2

.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

# IntelliJ based IDEs
.idea

# Finder (MacOS) folder config
.DS_Store

node_modules/
lib/
test/
dist/


================================================
FILE: .npmrc
================================================
tag-version-prefix=""

================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2020 Lars Kniep

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# @larscom/ng-chrome-extension

[![npm-release](https://img.shields.io/npm/v/@larscom/ng-chrome-extension.svg?label=npm)](https://www.npmjs.com/package/@larscom/ng-chrome-extension)
![npm](https://img.shields.io/npm/dt/@larscom/ng-chrome-extension)

> Easily create `Angular` Chrome Extensions (manifest v3)

The following scenarios are supported:

- Popup ✓
- New Tab ✓
- Options ✓
- Side Panel ✓
- Service Worker ✓
- Content Page ✓

## Disclaimer

This CLI tool should work on Linux/macOS, it is not tested on Windows.

## How to install

```bash
npm install -g @larscom/ng-chrome-extension
```

## Start creating a new project

```bash
ng-chrome new
```

![alt text](https://snipboard.io/OYcNzx.jpg 'ng-chrome CLI')

## How to use/develop

- change directory to your newly created project
- run `npm run start`
- goto: `chrome://extensions` in the browser and enable `'developer mode'`
- press `Load unpacked` and target the folder `angular/dist`

The project is automatically being watched, any changes to the files will recompile the project.

**NOTE**: changes to the **content page** and **service worker** scripts requires you to reload the extension in `chrome://extensions`

![alt text](https://snipboard.io/KToCI3.jpg 'Angular Chrome Popup')
![alt text](https://snipboard.io/VYfGoD.jpg 'Angular Chrome Tab')

## Build/package for production

- update version number inside `./angular/src/manifest.json`
- run `npm run build:production`
- upload `extension-build.zip` to the chrome webstore.

This will run a production build and will automatically zip it as a extension package in the root folder named: `extension-build.zip`

## Debugging

Run: `npm start`

Go to: Developer tools (inspect popup) => Sources => webpack

You can find your source files (TypeScript) over there.

## Upgrade Angular

After you have created a new project with `ng-chrome` and you want to update angular.

Just follow the regular upgrade guide of angular. See: https://update.angular.io/

## Angular folder

This folder contains the angular source code.
Each feature (popup,options,tab,side-panel) lives inside its own standalone component and gets lazily loaded.

see: `./angular/src/app/modules`

## Chrome folder

This folder contains the content page/service worker scripts and has its own `package.json` to manage it's dependencies.


================================================
FILE: package.json
================================================
{
  "name": "@larscom/ng-chrome-extension",
  "shortName": "ng-chrome",
  "version": "3.2.4",
  "description": "CLI to generate angular chrome extensions",
  "main": "./bin/main.js",
  "type": "module",
  "bin": {
    "ng-chrome": "bin/main.js"
  },
  "publishConfig": {
    "access": "public"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/larscom/ng-chrome-extension.git"
  },
  "bugs": {
    "url": "https://github.com/larscom/ng-chrome-extension/issues"
  },
  "homepage": "https://github.com/larscom/ng-chrome-extension#readme",
  "scripts": {
    "start": "rollup -c && node ./dist/bin/main.js",
    "build": "rollup -c"
  },
  "keywords": [
    "ng-chrome",
    "ng",
    "angular",
    "chrome",
    "extension",
    "google",
    "manifest",
    "rxjs"
  ],
  "author": "Lars Kniep",
  "license": "MIT",
  "dependencies": {
    "adm-zip": "^0.5.14",
    "axios": "^1.7.2",
    "clear": "^0.1.0",
    "commander": "^12.1.0",
    "figlet": "^1.7.0",
    "fs-extra": "^11.2.0",
    "inquirer": "^12.9.4",
    "kleur": "^4.1.5",
    "ora": "^8.0.1"
  },
  "devDependencies": {
    "@rollup/plugin-commonjs": "^29.0.0",
    "@rollup/plugin-json": "^6.1.0",
    "@rollup/plugin-node-resolve": "^15.2.3",
    "@rollup/plugin-typescript": "^11.1.6",
    "@types/adm-zip": "^0.5.5",
    "@types/bun": "latest",
    "@types/clear": "^0.1.4",
    "@types/figlet": "^1.5.8",
    "@types/fs-extra": "^11.0.4",
    "@types/inquirer": "^9.0.7",
    "@types/node": "^20.14.8",
    "rimraf": "^6.1.0",
    "rollup": "^4.18.0",
    "typescript": "^5.5.2"
  }
}


================================================
FILE: rollup.config.js
================================================
import commonjs from '@rollup/plugin-commonjs'
import json from '@rollup/plugin-json'
import resolve from '@rollup/plugin-node-resolve'
import typescript from '@rollup/plugin-typescript'

export default {
  input: './src/main.ts',
  output: {
    file: './dist/bin/main.js'
  },
  external: ['adm-zip', 'axios', 'clear', 'commander', 'figlet', 'fs-extra', 'inquirer', 'kleur', 'ora'],
  plugins: [typescript(), resolve(), commonjs(), json()]
}


================================================
FILE: src/logger.ts
================================================
import clear from 'clear'
import figlet from 'figlet'
import kleur from 'kleur'

const red = kleur.red
const yellow = kleur.yellow
const cyan = kleur.cyan
const green = kleur.green
const bold = kleur.bold

export class Logger {
  private readonly githubUrl: string

  constructor(githubUrl: string) {
    this.githubUrl = githubUrl
  }

  error(message: string, ...optionalParams: any[]) {
    console.log(red(`ERROR: ${message}`), ...optionalParams)
  }

  warn(message: string, ...optionalParams: any[]) {
    console.log(yellow(`WARN: ${message}`), ...optionalParams)
  }

  info(message: string, ...optionalParams: any[]) {
    console.log(cyan(`INFO: ${message}`), ...optionalParams)
  }

  showIntro(name: string, version: string) {
    clear({ fullClear: true })

    console.log(red(figlet.textSync(name, { horizontalLayout: 'full' })))
    console.log(green(version))
    console.log('---------------------------------------------------------------')
    console.log(`${this.githubUrl}`)
    console.log()
  }

  showOutro(name: string) {
    console.log()
    console.log('---------------------------------------------------------------')
    console.log(`You can now change directory to ${yellow(name)} and type the following commands:`)

    console.log()
    console.log(`   ${cyan('npm start')}`)
    console.log('       The project is automatically being watched/build')
    console.log(`       Go to ${yellow('chrome://extensions')} in the browser and enable '${bold('developer mode')}'`)
    console.log(`       Press ${yellow('Load unpacked')} and target the folder '${bold('angular/dist')}'`)

    console.log()
    console.log(`   ${cyan('npm run build:production')}`)
    console.log('       Creates a production ready zip file')
    console.log(`       Upload ${yellow('extension-build.zip')} directly to the chrome webstore`)
    console.log()
  }
}


================================================
FILE: src/main.ts
================================================
#!/usr/bin/env node

import admZip from 'adm-zip'
import axios from 'axios'
import { exec } from 'child_process'
import { program } from 'commander'
import fs from 'fs-extra'
import inquirer from 'inquirer'
import path from 'path'
import { Logger } from './logger'
import { Spinner } from './spinner'
import { version } from './version'

const packageName = 'ng-chrome'
const githubUrl = 'https://github.com/larscom/ng-chrome-extension'
const templateUrl = 'https://github.com/larscom/angular-chrome-extension/archive/refs/heads/master.zip'

const nameRegex = new RegExp(/^[a-z0-9-_]+$/)
const log = new Logger(githubUrl)
const spinner = new Spinner()

program
  .name(packageName)
  .description(`Create Google Chrome (V3) extensions with Angular!\n${githubUrl}`)
  .version(version)

  .command('new [name]')
  .description('Create a new Angular Chrome extension')
  .action(handleNewProject)

program.parse(process.argv, { from: 'node' })

async function handleNewProject(name: string): Promise<void> {
  log.showIntro(packageName, version)
  if (name) {
    const projectName = await parseName(name)
    await setupNewProject(projectName)
  } else {
    const { name } = await askName('name')
    const projectName = await parseName(name)
    await setupNewProject(projectName)
  }
}

async function setupNewProject(name: string): Promise<void> {
  await createProject(name)
  await installDeps(name)

  log.showOutro(name)
}

async function createProject(name: string): Promise<void> {
  const projectDir = getProjectDir(name)

  try {
    spinner.start('Creating new extension...')

    await downloadTemplate(projectDir, templateUrl)

    spinner.stop(`Created new Angular chrome extension at: ${projectDir}`)
  } catch (e) {
    spinner.stop()
    log.error('Failed creating new extension', e)
    process.exit(1)
  }
}

async function installDeps(name: string): Promise<void> {
  process.chdir(getProjectDir(name))

  try {
    spinner.start('Installing dependencies...')

    await execCmd('npm ci --legacy-peer-deps')
    await execCmd('(cd chrome && npm ci --legacy-peer-deps)')

    spinner.stop('Successfully installed dependencies')
  } catch (e) {
    spinner.stop()
    log.error('Failed installing dependencies', e)
    process.exit(1)
  }
}

async function downloadTemplate(dir: string, templateUrl: string): Promise<void> {
  await fs.mkdirp(dir)
  const zip = new admZip(await getZipBuffer(templateUrl))

  const entries = zip.getEntries()
  for (const entry of entries) {
    const path = `${dir}/${entry.entryName.replace('angular-chrome-extension-master/', '')}`
    if (path.includes('..')) {
      const msg = `Unexpected path: ${path}`
      log.error(msg)
      throw Error(msg)
    }

    if (entry.isDirectory) {
      fs.mkdirpSync(path)
    } else {
      fs.writeFileSync(path, entry.getData().toString('utf-8'))
    }
  }
}

async function parseName(name: string): Promise<string> {
  if (isValidName(name)) {
    const exist = await dirExists(name)
    if (exist) {
      log.error(`Project with name '${name}' already exists`)
      process.exit(1)
    }
    return name
  } else {
    log.error(`Project name invalid, must match: ${nameRegex.toString()}`)
    process.exit(1)
  }
}

async function getZipBuffer(url: string) {
  return await axios({ url, responseType: 'arraybuffer' }).then(({ data }) => data)
}

async function execCmd(command: string): Promise<void> {
  return new Promise<void>((resolve, reject) => exec(command, (error) => (error ? reject(error) : resolve())))
}

function dirExists(name: string): Promise<boolean> {
  return fs.pathExists(getProjectDir(name))
}

function getProjectDir(name: string): string {
  return path.join(process.cwd(), name)
}

function isValidName(name: string): boolean {
  return nameRegex.test(name)
}

function askName(name: string): Promise<any> {
  return inquirer.prompt([{ name, type: 'input', message: 'Enter a project name:' }])
}


================================================
FILE: src/spinner.ts
================================================
import ora from 'ora'

export class Spinner {
  private loader = ora({ color: 'green', hideCursor: true })

  start(text: string) {
    this.loader.start(text)
  }

  stop(text?: string) {
    this.loader.succeed(text)
  }
}


================================================
FILE: src/version.ts
================================================
export const version = '{{PLACEHOLDER_VERSION}}'


================================================
FILE: tsconfig.json
================================================
{
  "compilerOptions": {
    "target": "ES6",
    "module": "ESNext",
    "outDir": "./dist",
    "rootDir": "./src",
    "moduleResolution": "Node",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist"]
}
Download .txt
gitextract_1ulcxw8j/

├── .github/
│   └── workflows/
│       └── workflow.yml
├── .gitignore
├── .npmrc
├── LICENSE
├── README.md
├── package.json
├── rollup.config.js
├── src/
│   ├── logger.ts
│   ├── main.ts
│   ├── spinner.ts
│   └── version.ts
└── tsconfig.json
Download .txt
SYMBOL INDEX (22 symbols across 3 files)

FILE: src/logger.ts
  class Logger (line 11) | class Logger {
    method constructor (line 14) | constructor(githubUrl: string) {
    method error (line 18) | error(message: string, ...optionalParams: any[]) {
    method warn (line 22) | warn(message: string, ...optionalParams: any[]) {
    method info (line 26) | info(message: string, ...optionalParams: any[]) {
    method showIntro (line 30) | showIntro(name: string, version: string) {
    method showOutro (line 40) | showOutro(name: string) {

FILE: src/main.ts
  function handleNewProject (line 33) | async function handleNewProject(name: string): Promise<void> {
  function setupNewProject (line 45) | async function setupNewProject(name: string): Promise<void> {
  function createProject (line 52) | async function createProject(name: string): Promise<void> {
  function installDeps (line 68) | async function installDeps(name: string): Promise<void> {
  function downloadTemplate (line 85) | async function downloadTemplate(dir: string, templateUrl: string): Promi...
  function parseName (line 106) | async function parseName(name: string): Promise<string> {
  function getZipBuffer (line 120) | async function getZipBuffer(url: string) {
  function execCmd (line 124) | async function execCmd(command: string): Promise<void> {
  function dirExists (line 128) | function dirExists(name: string): Promise<boolean> {
  function getProjectDir (line 132) | function getProjectDir(name: string): string {
  function isValidName (line 136) | function isValidName(name: string): boolean {
  function askName (line 140) | function askName(name: string): Promise<any> {

FILE: src/spinner.ts
  class Spinner (line 3) | class Spinner {
    method start (line 6) | start(text: string) {
    method stop (line 10) | stop(text?: string) {
Condensed preview — 12 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (17K chars).
[
  {
    "path": ".github/workflows/workflow.yml",
    "chars": 1226,
    "preview": "name: workflow\n\non:\n  push:\n    tags:\n      - '*.*.*'\n    branches:\n      - '**'\n  pull_request:\n    branches:\n      - m"
  },
  {
    "path": ".gitignore",
    "chars": 2265,
    "preview": "# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore\n\n# Logs\n\nlogs\n_.log\nnpm-debug.log_\nyar"
  },
  {
    "path": ".npmrc",
    "chars": 21,
    "preview": "tag-version-prefix=\"\""
  },
  {
    "path": "LICENSE",
    "chars": 1067,
    "preview": "MIT License\n\nCopyright (c) 2020 Lars Kniep\n\nPermission is hereby granted, free of charge, to any person obtaining a copy"
  },
  {
    "path": "README.md",
    "chars": 2370,
    "preview": "# @larscom/ng-chrome-extension\n\n[![npm-release](https://img.shields.io/npm/v/@larscom/ng-chrome-extension.svg?label=npm)"
  },
  {
    "path": "package.json",
    "chars": 1582,
    "preview": "{\n  \"name\": \"@larscom/ng-chrome-extension\",\n  \"shortName\": \"ng-chrome\",\n  \"version\": \"3.2.4\",\n  \"description\": \"CLI to g"
  },
  {
    "path": "rollup.config.js",
    "chars": 444,
    "preview": "import commonjs from '@rollup/plugin-commonjs'\nimport json from '@rollup/plugin-json'\nimport resolve from '@rollup/plugi"
  },
  {
    "path": "src/logger.ts",
    "chars": 1873,
    "preview": "import clear from 'clear'\nimport figlet from 'figlet'\nimport kleur from 'kleur'\n\nconst red = kleur.red\nconst yellow = kl"
  },
  {
    "path": "src/main.ts",
    "chars": 3925,
    "preview": "#!/usr/bin/env node\n\nimport admZip from 'adm-zip'\nimport axios from 'axios'\nimport { exec } from 'child_process'\nimport "
  },
  {
    "path": "src/spinner.ts",
    "chars": 225,
    "preview": "import ora from 'ora'\n\nexport class Spinner {\n  private loader = ora({ color: 'green', hideCursor: true })\n\n  start(text"
  },
  {
    "path": "src/version.ts",
    "chars": 49,
    "preview": "export const version = '{{PLACEHOLDER_VERSION}}'\n"
  },
  {
    "path": "tsconfig.json",
    "chars": 337,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"ES6\",\n    \"module\": \"ESNext\",\n    \"outDir\": \"./dist\",\n    \"rootDir\": \"./src\",\n  "
  }
]

About this extraction

This page contains the full source code of the larscom/ng-chrome-extension GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 12 files (15.0 KB), approximately 4.2k tokens, and a symbol index with 22 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!