A chrome extension that replaces the new tab.
Download ext.crx and plugins.zip from here.
Go to chrome://extensions in your browser, then drag ext.crx inside.
Navigate to the settings page to add buttons, plugins, and themes.
IMPORTANT: Chrome 35 and above disallow installation of non-webstore extensions. See this for possible workarounds.
Run npm install then gulp pack, and the extension can be found packed in the ./build/dist directory, or unpacked in the ./build/src directory.
- Run
npm initin the plugin's folder and fill out the info - Use
npm install --saveto add your dependencies - Create a
package.jsonlike the one described below - Run the bundler (
node bundler.js), with the first argument the plugin folder, and the second a path to write the compiled plugin file to
main: the main page, the 'new tab'settings: the extension's options pageglobal: matches any view
Any of these can access a plugin api object called api.
main: runs on the main viewsettings: runs on the settings viewglobal: runs on any view, but before the view-specific hookinit: is executed only on plugin install/update
api.setting(settingName): get value of specified setting, or its default if it's unsetapi.insertStyle(css): insert the given css string into an inline style elementapi.registerAction(displayName, actionPathname, handler): register a handler for a custom button action. Run this in theglobalhookapi.insertView(htmlElement, order, alignment): (only in themainhook) insert a view to the default activity.alignmentcan beleft,centerorright.orderis the order within each alignment, and it maps to the css propertyorderapi.pushActivity(activityName, htmlElement): (only in themainhook) navigate to another activity. When called, the current activity's element will be hidden, the given element will be shown, theactivityNamewill replace the tab title and navbar title, and a button to navigate back appears in the navbarapi.popActivity(): (only in themainhook) hide current activity, and show previous one. If the default activity is shown, this function is a no-op
This file is used by npm and by the bundler. Paths are relative to the package.json's directory.
{
"pluginName": "displayName",
"description": "message",
"author": "name",
"version": "1.1.1",
"settings": [],
"dependencies": {},
"webpackConfig": "path/to/webpack.config",
"html": {
"main": {
"path/to/file1.html": "querySelector1",
"path/to/file2.html": "querySelector2"
...
},
"settings": {
"path/to/file1.html": "querySelector1",
"path/to/file2.html": "querySelector2"
...
},
"global": {
"path/to/file1.html": "querySelector1",
"path/to/file2.html": "querySelector2"
...
}
},
"css": {
"main": ["path/to/file1.css", "path/to/file2.css", ...],
"settings": ["path/to/file3.css", "path/to/file4.css", ...],
"global": ["path/to/file5.css", "path/to/file6.css", ...]
},
"js": {
"main": "path/to/file1.js",
"settings": "path/to/file2.js",
"global": "path/to/file3.js",
"init": "path/to/file4.js"
}
}
pluginName: (string) name of plugindescription: (string) plugin descriptionauthor: (string) self-explanatoryversion: (string) semver version stringsettings: (array of objects) setting format described below. Setting values are preserved during updates only if thenameandtypeproperties are unchangeddependencies: (object) npm's dependencies fieldwebpackConfig: (path string) path to a webpack config to be require'd. Theentryandoutputproperties are handled by the bundlerhtml: (object) each property represents a view. For each view, there are html files associated with a query selector. The html will be inserted in the element obtained from the selectorcss: (object) each property represents a view. The css files for each view are concatenated, and the merged data is appended to an inline stylesheet after the html has been insertedjs: (object) each property represents a hook. The js at the specified path for each hook is an entry point for webpack
Themes are just JSON files:
{
"name": "Default Theme",
"isDark": false,
"background": "#FAFAFA",
"main": "#FF9800",
"accent": "#B2FF59",
"deleted": undefined
}
name: (string) name of themeisDark: (boolean) whether or not the theme should be considered "dark", as dark themes trigger light styles for some elements/textbackground,main,accent: (css color strings) base colors for the UIdeleted: (optional boolean) if true, it signals that this theme was "deleted" by the user; this element will be removed before saving to storage
Usually, this is to be generated by the bundler from the package.json above. This should be valid JSON.
{
"name": "displayName",
"desc": "message",
"author": "name",
"version": "1.1.1",
"settings": [],
"js": {
"init": "(function (api) {})()",
"global": "(function (api) {})()",
"main": "(function (api) {})()",
"settings": "(function (api) {})()"
},
"css": {
"main": "cssText",
"settings": "cssText",
},
"html": {
"main": {
"querySelector": "htmlToAdd"
...
},
"settings": {
"querySelector": "htmlToAdd"
...
}
},
"deleted": undefined
}
name: (string) see above, is equivalent topluginNamedesc: (string) see above, is equivalent todescriptionauthor: (string) see aboveversion: (semver string) see abovesettings: (array of setting objects) see abovejs: (object) all functions are stringified IIFEs, each property is a hookcss: (object) the css from each property will be added to it's respective viewhtml: (object of objects) every property targets a view. For every view,htmlToAddwill be added at the position specified by thequerySelector. There can be multiplequerySelectorsdeleted: (optional boolean) if true, it signals that this plugin was "deleted" by the user; this element will be removed before saving to storage
{
"name": "displayName",
"desc": "message",
"type": "type",
"valid": [],
"default": "",
"value": undefined,
"isVisible": true
}
name: (string) title of settingdesc: (optional string) description of settingtype: (enum string) input types, orenumvalid: (array of objects) iftypeisenum, this is a list of objects with anameand avalueproperty, otherwise not defineddefault: (any) if the value is not set, this value should be used as a defaultvalue: (any) undefined until setisVisible: (boolean) if false, it means this 'setting' is just storage
{
"kind": "default",
"pictureType": "image",
"imagePath": "http://example.com",
"ligatureName": "",
"href": "http://example.com",
"text": "Button",
"position": 3.14,
"hotkey": "K",
"deleted": undefined
}
kind: (enum string) what kind of "button" it is; values aredefault,divider,subheaderpictureType: (enum string) if it isimage, use theimagePath, if it isiconuseligatureNameimagePath: (uri string) path to imageligatureName: (string) name of material iconhref: (uri string) where does it point totext: (string) displyed textposition: (float) used to determine order of buttonshotkey: (string) using alt+key triggers the buttondeleted: (optional boolean) if true, it signals that this button was "deleted" by the user; this element will be removed before saving to storage
This API is used in /plugins/reddit/main.js.
The page will perform GET requests for the user data associated with the given username.


