Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
dong-qian committed Jan 15, 2021
0 parents commit bb5633c
Show file tree
Hide file tree
Showing 51 changed files with 304,216 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": ["react-app"]
}
2 changes: 2 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
GENERATE_SOURCEMAP=false
INLINE_RUNTIME_CHUNK=false
2 changes: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
build
43 changes: 43 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"parser": "babel-eslint",
"root": true, // Make sure eslint picks up the config at the root of the directory
"parserOptions": {
"ecmaVersion": 2020, // Use the latest ecmascript standard
"sourceType": "module", // Allows using import/export statements
"ecmaFeatures": {
"jsx": true // Enable JSX since we're using React
}
},
"settings": {
"react": {
"version": "detect" // Automatically detect the react version
}
},
"env": {
"browser": true, // Enables browser globals like window and document
"amd": true, // Enables require() and define() as global variables as per the amd spec.
"node": true, // Enables Node.js global variables and Node.js scoping.
"es6": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:jsx-a11y/recommended",
"plugin:prettier/recommended", // Make this the last element so prettier config overrides other formatting rules
"prettier/react"
],
"plugins": ["simple-import-sort"],
"rules": {
"react/react-in-jsx-scope": "off",
"react/prop-types": "off",
"jsx-a11y/anchor-is-valid": [
"error",
{
"components": ["Link"],
"specialLink": ["hrefLeft", "hrefRight"],
"aspects": ["invalidHref", "preferButton"]
}
],
"prettier/prettier": ["error", { "trailingComma": "none" }]
}
}
36 changes: 36 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local

# vercel
.vercel

extension
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
build
11 changes: 11 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"semi": true,
"arrowParens": "avoid",
"bracketSpacing": true,
"tabWidth": 2,
"printWidth": 100,
"singleQuote": true,
"trailingComma": "none",
"jsxBracketSameLine": false,
"useTabs": false
}
117 changes: 117 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# Linkes

## About this extension

This is an extension to help user quickly open thier faviour bookmarks.

## Running The Extension

1. Run `npm install` in the folder to install dependencies
2. Run `npm run dev` to start the development server (auto refreshes your extension on change)
3. Navigate to `chrome://extensions` in your browser
4. Ensure `Developer mode` is `enabled` (top right)
5. Click `Load unpacked` in the top left
6. Select the `/build` folder in this directory

After completing the above steps, you should see the developer, unpacked version appear in your extension list as well as the extension icon appear in your browser bar alongside the other extensions you may have installed.

To trigger the extension, simply click the extension icon.

### All Available Commands

- `npm run build` - create a production ready build
- `npm run postbuild` - copies required Chrome extension files after build has completed
- `npm run assemble` - creates a production ready build and zips all files needed to publish in the web store to `extension.zip`
- `npm run dev` - creates a development server that can be used for hot reloading inside the Google Chrome extension ecosystem (see steps 1-6 above)
- `npm run test` - runs any Jest tests you may have
- `npm run pretty` - runs prettier on the `/src` folder
- `npm run lint` - runs eslint on the `/src` folder
- `npm run build:tailwind` - builds the Tailwind CSS files

## Making Changes

Afer starting the dev server via `npm run dev`, changes will be automatically be rebuilt to `/build` via webpack and the unpacked Chrome extension will automatically be refreshed for you behind the scenes, meaning you don't need to press the refresh button on `chrome://extensions`. Note: you may need to re-toggle or refresh the popup / page to see actual UI changes reflected there after a rebuild (i.e. re-open it again by clicking the icon again).

## Extending The Template

Extending this template would be similar to working on any other Create React App React application. The core of the React app lives in the `/src` and is unopinionated in terms of how it's been setup other than the basic routing and Tailwind CSS.

## Manifest Explained

There are 2 key sections of the manifest with this example template:

### Browser Action

```
"browser_action": {
"default_icon": "icon.png",
"default_title": "Open Full Page"
},
```

This portion of the manifest is used to define how the browser action (extension icon) should behave. In this case, we don't define anything other than the icon and the title, as the clicking action will be handled by the background script in `background.js`.

### Background Scripts

```
"browser_action": {
"default_icon": {
"32": "icon.png"
},
"default_title": "Open Full Page"
},
```

This portion of the manifest tells the browser that we want to run some scripts in the background while this extension is enabled. In the case of this example template, the background script is there to listen for clicks on the extension icon and create a new tab pointing to `index.html` when those clicks occur. The background script lives outside of the `/src` folder as it shouldn't contain any React code.

## Preparing to Publish

To prepare for publish, simply run `npm run assemble` which will kick off a production-ready build step and then zip all the contents to `extension.zip` in the folder root. This zip file will include all the files you need for your extension to be uploaded to the web store.

Note: if this isn't your first publish of your extension, make sure you bump up the verison number in the manifest (for example, `1.0.0` to `1.0.1`), as the web store will require a new version in every update you upload.

## Using TypeScript

TypeScript can easily be configured to work with this template as it's based on `create-react-app`. To get started, first run:

```
npm install --save typescript @types/node @types/react @types/react-dom @types/jest
```

Afterwards, create a `tsconfig.json` in the folder root with your desired settings. If you want, you can use the CRA default:

```
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react"
},
"include": [
"src"
]
}
```

Next, create a `react-app-env.d.ts` file in the `/src` folder with the following content:

```
/// <reference types="react-scripts" />
```

Finally, rename files to `.tsx` or `.ts` in the `/src` folder and you're ready to go!
18 changes: 18 additions & 0 deletions background.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*global chrome*/

/*
* This file includes all background scripts running while the extension
* is active. React code should not be placed here.
*/

chrome.commands.onCommand.addListener(function (command) {
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
if (command === 'toggle-search-modal') {
chrome.tabs.sendMessage(tabs[0].id, { action: 'toggle-search-modal' });
}

if (command === 'toggle-bookmarks-modal') {
chrome.tabs.sendMessage(tabs[0].id, { action: 'toggle-bookmarks-modal' });
}
});
});
91 changes: 91 additions & 0 deletions config/env.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
'use strict';

const fs = require('fs');
const path = require('path');
const paths = require('./paths');

// Make sure that including paths.js after env.js will read .env variables.
delete require.cache[require.resolve('./paths')];

const NODE_ENV = process.env.NODE_ENV;
if (!NODE_ENV) {
throw new Error('The NODE_ENV environment variable is required but was not specified.');
}

// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
const dotenvFiles = [
`${paths.dotenv}.${NODE_ENV}.local`,
`${paths.dotenv}.${NODE_ENV}`,
// Don't include `.env.local` for `test` environment
// since normally you expect tests to produce the same
// results for everyone
NODE_ENV !== 'test' && `${paths.dotenv}.local`,
paths.dotenv
].filter(Boolean);

// Load environment variables from .env* files. Suppress warnings using silent
// if this file is missing. dotenv will never modify any environment variables
// that have already been set. Variable expansion is supported in .env files.
// https://github.com/motdotla/dotenv
// https://github.com/motdotla/dotenv-expand
dotenvFiles.forEach(dotenvFile => {
if (fs.existsSync(dotenvFile)) {
require('dotenv-expand')(
require('dotenv').config({
path: dotenvFile
})
);
}
});

// We support resolving modules according to `NODE_PATH`.
// This lets you use absolute paths in imports inside large monorepos:
// https://github.com/facebook/create-react-app/issues/253.
// It works similar to `NODE_PATH` in Node itself:
// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.
// Otherwise, we risk importing Node.js core modules into an app instead of webpack shims.
// https://github.com/facebook/create-react-app/issues/1023#issuecomment-265344421
// We also resolve them to make sure all tools using them work consistently.
const appDirectory = fs.realpathSync(process.cwd());
process.env.NODE_PATH = (process.env.NODE_PATH || '')
.split(path.delimiter)
.filter(folder => folder && !path.isAbsolute(folder))
.map(folder => path.resolve(appDirectory, folder))
.join(path.delimiter);

// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
// injected into the application via DefinePlugin in webpack configuration.
const REACT_APP = /^REACT_APP_/i;

function getClientEnvironment(publicUrl) {
const raw = Object.keys(process.env)
.filter(key => REACT_APP.test(key))
.reduce(
(env, key) => {
env[key] = process.env[key];
return env;
},
{
// Useful for determining whether we’re running in production mode.
// Most importantly, it switches React into the correct mode.
NODE_ENV: process.env.NODE_ENV || 'development',
// Useful for resolving the correct path to static assets in `public`.
// For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />.
// This should only be used as an escape hatch. Normally you would put
// images into the `src` and `import` them in code to get their paths.
PUBLIC_URL: publicUrl
}
);
// Stringify all values so we can feed into webpack DefinePlugin
const stringified = {
'process.env': Object.keys(raw).reduce((env, key) => {
env[key] = JSON.stringify(raw[key]);
return env;
}, {})
};

return { raw, stringified };
}

module.exports = getClientEnvironment;
14 changes: 14 additions & 0 deletions config/jest/cssTransform.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use strict';

// This is a custom Jest transformer turning style imports into empty objects.
// http://facebook.github.io/jest/docs/en/webpack.html

module.exports = {
process() {
return 'module.exports = {};';
},
getCacheKey() {
// The output is always the same.
return 'cssTransform';
}
};
40 changes: 40 additions & 0 deletions config/jest/fileTransform.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
'use strict';

const path = require('path');
const camelcase = require('camelcase');

// This is a custom Jest transformer turning file imports into filenames.
// http://facebook.github.io/jest/docs/en/webpack.html

module.exports = {
process(src, filename) {
const assetFilename = JSON.stringify(path.basename(filename));

if (filename.match(/\.svg$/)) {
// Based on how SVGR generates a component name:
// https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6
const pascalCaseFilename = camelcase(path.parse(filename).name, {
pascalCase: true
});
const componentName = `Svg${pascalCaseFilename}`;
return `const React = require('react');
module.exports = {
__esModule: true,
default: ${assetFilename},
ReactComponent: React.forwardRef(function ${componentName}(props, ref) {
return {
$$typeof: Symbol.for('react.element'),
type: 'svg',
ref: ref,
key: null,
props: Object.assign({}, props, {
children: ${assetFilename}
})
};
}),
};`;
}

return `module.exports = ${assetFilename};`;
}
};
Loading

0 comments on commit bb5633c

Please sign in to comment.