Skip to content

Commit

Permalink
Merge pull request #21 from dutiyesh/feature/add-typescript-support
Browse files Browse the repository at this point in the history
Add TypeScript support
  • Loading branch information
dutiyesh authored Apr 17, 2022
2 parents 27e25d4 + 6ce8f7b commit 92637d8
Show file tree
Hide file tree
Showing 58 changed files with 780 additions and 4 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,17 @@ chrome-extension-cli my-extension --override-page=history // Override Histo

Creates a Panel inside developer tools.

#### `chrome-extension-cli my-extension --language`

Creates an extension for supported languages like JavaScript and TypeScript.<br>
By default extension is created for JavaScript language and you can also pass other value to `--language` option to create extension for TypeScript.

```
chrome-extension-cli my-extension // Language JavaScript (default)
chrome-extension-cli my-extension --language=javascript // Language JavaScript
chrome-extension-cli my-extension --language=typescript // Language TypeScript
```

## Contributing

See the [contribution guide](CONTRIBUTING.md) and join the contributors!
Expand Down
File renamed without changes.
File renamed without changes.
75 changes: 75 additions & 0 deletions config/typescript/webpack.common.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
'use strict';

const SizePlugin = require('size-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

const PATHS = require('./paths');

// To re-use webpack configuration across templates,
// CLI maintains a common webpack configuration file - `webpack.common.js`.
// Whenever user creates an extension, CLI adds `webpack.common.js` file
// in template's `config` folder
const common = {
output: {
// the build folder to output bundles and assets in.
path: PATHS.build,
// the filename template for entry chunks
filename: '[name].js',
},
stats: {
all: false,
errors: true,
builtAt: true,
},
module: {
rules: [
// Check for TypeScript files
{
test: /\.ts$/,
use: ['ts-loader'],
},
// Help webpack in understanding CSS files imported in .js files
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
// Check for images imported in .js files and
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
options: {
outputPath: 'images',
name: '[name].[ext]',
},
},
],
},
],
},
resolve: {
// Help webpack resolve these extensions in order
extensions: ['.ts', '.js'],
},
plugins: [
// Print file sizes
new SizePlugin(),
// Copy static assets from `public` folder to `build` folder
new CopyWebpackPlugin({
patterns: [
{
from: '**/*',
context: 'public',
},
],
}),
// Extract CSS into separate files
new MiniCssExtractPlugin({
filename: '[name].css',
}),
],
};

module.exports = common;
89 changes: 86 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,17 @@ const generateReadme = require('./scripts/readme');
const tryGitInit = require('./scripts/git-init');

let projectName;
const LANGUAGES = ['javascript', 'typescript'];
const OVERRIDE_PAGES = ['newtab', 'bookmarks', 'history'];
const TS_CONFIG = {
compilerOptions: {
rootDir: 'src',
target: 'es6',
module: 'commonjs',
esModuleInterop: true,
strict: true,
},
};

const program = new commander.Command(packageFile.name)
.version(packageFile.version)
Expand All @@ -28,6 +38,10 @@ const program = new commander.Command(packageFile.name)
'override default page like New Tab, Bookmarks, or History page'
)
.option('--devtools', 'add features to Chrome Developer Tools')
.option(
'--language [language-name]',
'language like JavaScript and TypeScript'
)
.on('--help', () => {
console.log(` Only ${chalk.green('<project-directory>')} is required.`);
})
Expand Down Expand Up @@ -57,6 +71,14 @@ function isOverridePageNameValid(name) {
return false;
}

function isLanguageNameValid(name) {
if (name === true || LANGUAGES.includes(name)) {
return true;
}

return false;
}

function logOverridePageError() {
console.error(
`${chalk.red('Invalid page name passed to option:')} ${chalk.cyan(
Expand All @@ -79,6 +101,28 @@ function logOverridePageError() {
process.exit(1);
}

function logLanguageError() {
console.error(
`${chalk.red('Invalid language name passed to option:')} ${chalk.cyan(
'--language'
)}`
);
console.log();
console.log(
`You can pass language name as ${chalk.cyan('javascript')} or ${chalk.cyan(
'typescript'
)}.`
);
console.log();
console.log('For example:');
console.log(
` ${chalk.cyan(program.name())} ${chalk.green(
'my-extension'
)} ${chalk.cyan('--language')} ${chalk.green('typescript')}`
);
process.exit(1);
}

function logOptionsConflictError() {
console.error(
`${chalk.red(
Expand All @@ -90,9 +134,10 @@ function logOptionsConflictError() {
process.exit(1);
}

function createExtension(name, { overridePage, devtools }) {
function createExtension(name, { overridePage, devtools, language }) {
const root = path.resolve(name);
let overridePageName;
let languageName = 'javascript';

if (overridePage) {
if (isOverridePageNameValid(overridePage)) {
Expand All @@ -106,6 +151,14 @@ function createExtension(name, { overridePage, devtools }) {
}
}

if (language) {
if (isLanguageNameValid(language)) {
languageName = language === true ? 'javascript' : language;
} else {
logLanguageError();
}
}

checkAppName(name);
fs.ensureDirSync(name);

Expand Down Expand Up @@ -141,6 +194,14 @@ function createExtension(name, { overridePage, devtools }) {
JSON.stringify(appPackage, null, 2)
);

// Create tsconfig file in project directory
if (languageName === 'typescript') {
fs.writeFileSync(
path.join(root, 'tsconfig.json'),
JSON.stringify(TS_CONFIG, null, 2)
);
}

let command = 'npm';
let args = ['install', '--save-dev'];

Expand All @@ -156,6 +217,10 @@ function createExtension(name, { overridePage, devtools }) {
'file-loader@^6.0.0'
);

if (languageName === 'typescript') {
args.push('[email protected]', '[email protected]', '@types/[email protected]');
}

console.log('Installing packages. This might take a couple of minutes.');
console.log(
`Installing ${chalk.cyan('webpack')}, ${chalk.cyan(
Expand All @@ -181,10 +246,27 @@ function createExtension(name, { overridePage, devtools }) {
templateName = 'popup';
}

fs.copySync(path.resolve(__dirname, 'templates', templateName), root);
fs.copySync(
path.resolve(__dirname, 'templates', languageName, templateName),
root
);

// Copy common files between languages
fs.copySync(
path.resolve(__dirname, 'templates', 'shared', templateName),
root
);

fs.copySync(
path.resolve(__dirname, 'config', languageName),
path.join(root, 'config')
);

// Copy common webpack configuration file
fs.copySync(path.resolve(__dirname, 'config'), path.join(root, 'config'));
fs.copySync(
path.resolve(__dirname, 'config', 'shared'),
path.join(root, 'config')
);

// Rename gitignore after the fact to prevent npm from renaming it to .npmignore
// See: https://github.com/npm/npm/issues/1862
Expand Down Expand Up @@ -289,4 +371,5 @@ function createExtension(name, { overridePage, devtools }) {
createExtension(projectName, {
overridePage: program.overridePage,
devtools: program.devtools,
language: program.language,
});
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"chrome-extension-cli": "index.js"
},
"scripts": {
"format": "prettier --single-quote --trailing-comma es5 --write 'index.js' '{config,scripts,utils,templates}/**/*.{js,css}'"
"format": "prettier --single-quote --trailing-comma es5 --write 'index.js' '{config,scripts,utils,templates}/**/*.{js,ts,css}'"
},
"keywords": [
"chrome",
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes.
8 changes: 8 additions & 0 deletions templates/typescript/chrome.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// A temporary solution to ignore TypeScript errors
declare var chrome: {
runtime: any;
panel: any;
devtools: any;
storage: any;
tabs: any;
};
19 changes: 19 additions & 0 deletions templates/typescript/devtools/config/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use strict';

const { merge } = require('webpack-merge');

const common = require('./webpack.common.js');
const PATHS = require('./paths');

// Merge webpack configuration files
const config = (env, argv) =>
merge(common, {
entry: {
devtools: PATHS.src + '/devtools.ts',
panel: PATHS.src + '/panel.ts',
background: PATHS.src + '/background.ts',
},
devtool: argv.mode === 'production' ? false : 'source-map',
});

module.exports = config;
19 changes: 19 additions & 0 deletions templates/typescript/devtools/src/background.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use strict';

// With background scripts you can communicate with popup
// and contentScript files.
// For more information on background script,
// See https://developer.chrome.com/extensions/background_pages

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.type === 'GREETINGS') {
const message: string = `Hi Pan, my name is Bac. I am from Background. It's great to hear from you.`;

// Log message coming from the `request` parameter
console.log(request.payload.message);
// Send a response message
sendResponse({
message,
});
}
});
10 changes: 10 additions & 0 deletions templates/typescript/devtools/src/devtools.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use strict';

// A DevTools extension adds functionality to the Chrome DevTools.
// For more information on DevTools,
// See https://developer.chrome.com/extensions/devtools

// Create a panel named `My Panel`
chrome.devtools.panels.create('My Panel', '', 'panel.html', panel => {
console.log('Panel was successfully created!');
});
55 changes: 55 additions & 0 deletions templates/typescript/devtools/src/panel.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/* normalize css starts here */
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* normalize css ends here */

html {
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,
sans-serif;
color: #222;
}

body {
width: 100vw;
height: 100vh;
background-color: #fff;
}

.app {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
text-align: center;
padding: 20px;
}

code {
font-size: 12px;
font-family: inherit;
background-color: rgba(254, 237, 185, 0.3);
padding: 2px 4px;
border-radius: 2px;
}

.title {
font-size: 18px;
margin-bottom: 10px;
}

.message {
font-size: 22px;
}

.divider {
margin: 30px auto;
width: 50px;
border: 0.5px dashed #000;
opacity: 0.2;
}
Loading

0 comments on commit 92637d8

Please sign in to comment.