🎉 Hello World

This commit is contained in:
2018-04-08 22:33:36 +02:00
commit 21d1e6f0ef
48 changed files with 1248 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
{
"appName": {
"message": "Ext Starter",
"description": "The name of the extension."
},
"appDescription": {
"message": "Boilerplate for building cross browser extensions",
"description": "The description of the extension."
},
"btnTooltip": {
"message": "Ext Starter",
"description": "Tooltip for the button."
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
src/icons/favicon-16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/icons/favicon-32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
src/icons/favicon-96x96.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

BIN
src/icons/icon-128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
src/icons/icon-16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

BIN
src/icons/icon-19.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 B

BIN
src/icons/icon-38.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
src/icons/icon-64.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

0
src/images/.gitkeep Normal file
View File

View File

View File

View File

View File

53
src/options.html Normal file
View File

@@ -0,0 +1,53 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<link href="styles/options.css" rel="stylesheet">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Options & Settings</title>
</head>
<body class="wrap">
<div class="grid">
<div class="unit whole center-on-mobiles">
<div class="heading">
<h1>Shikiryu Bookmarklet</h1>
<p class="lead">Save this page by email for later read</p>
</div>
</div>
</div>
<section class="content">
<div id="msg"></div>
</section>
<section class="content">
<div class="grid">
<div class="unit whole center-on-mobiles">
<div class="option">
<h5>URL</h5>
<input type="text" name="url" value="https://bookmarklet.shikiryu.com" />
</div>
<div class="option">
<h5>Token</h5>
<input type="text" name="token" value="" />
</div>
</div>
</div>
</section>
<footer class="main-footer">
<div class="grid">
<div class="unit whole center-on-mobiles">
<p class="text-center text-muted">
&copy; Shikiryu (thanks to https://github.com/EmailThis/extension-boilerplate)
</p>
</div>
</div>
</footer>
<script src="scripts/options.js"></script>
</body>
</html>

24
src/popup.html Normal file
View File

@@ -0,0 +1,24 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<link href="styles/popup.css" rel="stylesheet">
</head>
<body>
<div id="app" class="popup-content">
<h1 class="app-name">Extension Boilerplate</h1>
<div id="display-container"></div>
<footer>
<p>
<small>
<a href="#" class="js-options">Options</a>
</small>
</p>
</footer>
</div>
<script src="scripts/popup.js"></script>
</body>
</html>

31
src/scripts/background.js Normal file
View File

@@ -0,0 +1,31 @@
import ext from "./utils/ext";
import storage from "./utils/storage";
ext.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if(request.action === "perform-save") {
var data = JSON.parse(request.data);
var url;
var token;
storage.get('url', function(resp) {
url = resp.url;
storage.get('token', function(resp) {
token = resp.token;
console.log("Extension Type: ", "/* @echo extension */");
console.log("PERFORM AJAX", request.data);
var destination = url+"?v=1&u="+encodeURIComponent(data.url)+"&t="+encodeURIComponent(data.title)+"&m="+encodeURIComponent(token);
console.log("Destination: ", destination);
fetch(destination)
.then(function(response) {
console.log(response);
});
sendResponse({ action: "saved" });
});
});
}
}
);

View File

@@ -0,0 +1,34 @@
import ext from "./utils/ext";
var extractTags = () => {
var url = document.location.href;
if(!url || !url.match(/^http/)) return;
var data = {
title: "",
description: "",
url: document.location.href
}
var ogTitle = document.querySelector("meta[property='og:title']");
if(ogTitle) {
data.title = ogTitle.getAttribute("content")
} else {
data.title = document.title
}
var descriptionTag = document.querySelector("meta[property='og:description']") || document.querySelector("meta[name='description']")
if(descriptionTag) {
data.description = descriptionTag.getAttribute("content")
}
return data;
}
function onRequest(request, sender, sendResponse) {
if (request.action === 'process-page') {
sendResponse(extractTags())
}
}
ext.runtime.onMessage.addListener(onRequest);

20
src/scripts/livereload.js Normal file
View File

@@ -0,0 +1,20 @@
'use strict';
import ext from "./utils/ext";
var LIVERELOAD_HOST = 'localhost:';
var LIVERELOAD_PORT = 35729;
var connection = new WebSocket('ws://' + LIVERELOAD_HOST + LIVERELOAD_PORT + '/livereload');
connection.onerror = function (error) {
console.log('reload connection got error:', error);
};
connection.onmessage = function (e) {
if (e.data) {
var data = JSON.parse(e.data);
if (data && data.command === 'reload') {
ext.runtime.reload();
}
}
};

28
src/scripts/options.js Normal file
View File

@@ -0,0 +1,28 @@
import ext from "./utils/ext";
import storage from "./utils/storage";
var urlInput = document.querySelector("[name=url]");
var tokenInput = document.querySelector("[name=token]");
var message = document.getElementById("msg");
storage.get('url', function(resp) {
urlInput.value = resp.url || "https://bookmarklet.shikiryu.com";
});
storage.get('token', function(resp) {
tokenInput.value = resp.token;
});
urlInput.addEventListener("blur", function(e) {
var value = this.value;
storage.set({ url: value }, function() {
message.innerHTML = "URL changed!";
});
});
tokenInput.addEventListener("blur", function(e) {
var value = this.value;
storage.set({ token: value }, function() {
message.innerHTML = "Token saved!";
});
});

63
src/scripts/popup.js Normal file
View File

@@ -0,0 +1,63 @@
import ext from "./utils/ext";
import storage from "./utils/storage";
var popup = document.getElementById("app");
storage.get('color', function(resp) {
var color = resp.color;
if(color) {
popup.style.backgroundColor = color
}
});
var template = (data) => {
var json = JSON.stringify(data);
return (`
<div class="site-description">
<h3 class="title">${data.title}</h3>
<p class="description">${data.description}</p>
<a href="${data.url}" target="_blank" class="url">${data.url}</a>
</div>
<div class="action-container">
<button data-bookmark='${json}' id="save-btn" class="btn btn-primary">Save</button>
</div>
`);
}
var renderMessage = (message) => {
var displayContainer = document.getElementById("display-container");
displayContainer.innerHTML = `<p class='message'>${message}</p>`;
}
var renderBookmark = (data) => {
var displayContainer = document.getElementById("display-container")
if(data) {
var tmpl = template(data);
displayContainer.innerHTML = tmpl;
} else {
renderMessage("Sorry, could not extract this page's title and URL")
}
}
ext.tabs.query({active: true, currentWindow: true}, function(tabs) {
var activeTab = tabs[0];
chrome.tabs.sendMessage(activeTab.id, { action: 'process-page' }, renderBookmark);
});
popup.addEventListener("click", function(e) {
if(e.target && e.target.matches("#save-btn")) {
e.preventDefault();
var data = e.target.getAttribute("data-bookmark");
ext.runtime.sendMessage({ action: "perform-save", data: data }, function(response) {
if(response && response.action === "saved") {
renderMessage("Your bookmark was saved successfully!");
} else {
renderMessage("Sorry, there was an error while saving your bookmark.");
}
})
}
});
var optionsLink = document.querySelector(".js-options");
optionsLink.addEventListener("click", function(e) {
e.preventDefault();
ext.tabs.create({'url': ext.extension.getURL('options.html')});
})

68
src/scripts/utils/ext.js Normal file
View File

@@ -0,0 +1,68 @@
const apis = [
'alarms',
'bookmarks',
'browserAction',
'commands',
'contextMenus',
'cookies',
'downloads',
'events',
'extension',
'extensionTypes',
'history',
'i18n',
'idle',
'notifications',
'pageAction',
'runtime',
'storage',
'tabs',
'webNavigation',
'webRequest',
'windows',
]
function Extension () {
const _this = this
apis.forEach(function (api) {
_this[api] = null
try {
if (chrome[api]) {
_this[api] = chrome[api]
}
} catch (e) {}
try {
if (window[api]) {
_this[api] = window[api]
}
} catch (e) {}
try {
if (browser[api]) {
_this[api] = browser[api]
}
} catch (e) {}
try {
_this.api = browser.extension[api]
} catch (e) {}
})
try {
if (browser && browser.runtime) {
this.runtime = browser.runtime
}
} catch (e) {}
try {
if (browser && browser.browserAction) {
this.browserAction = browser.browserAction
}
} catch (e) {}
}
module.exports = new Extension();

View File

@@ -0,0 +1,3 @@
import ext from "./ext";
module.exports = (ext.storage.sync ? ext.storage.sync : ext.storage.local);

View File

@@ -0,0 +1,132 @@
/*
* Gridism
* A simple, responsive, and handy CSS grid by @cobyism
* https://github.com/cobyism/gridism
*/
/* Preserve some sanity */
.grid,
.unit {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
/* Set up some rules to govern the grid */
.grid {
display: block;
clear: both;
}
.grid .unit {
float: left;
width: 100%;
padding: 10px;
}
/* This ensures the outer gutters are equal to the (doubled) inner gutters. */
.grid .unit:first-child { padding-left: 20px; }
.grid .unit:last-child { padding-right: 20px; }
/* Nested grids already have padding though, so let's nuke it */
.unit .unit:first-child { padding-left: 0; }
.unit .unit:last-child { padding-right: 0; }
.unit .grid:first-child > .unit { padding-top: 0; }
.unit .grid:last-child > .unit { padding-bottom: 0; }
/* Let people nuke the gutters/padding completely in a couple of ways */
.no-gutters .unit,
.unit.no-gutters {
padding: 0 !important;
}
/* Wrapping at a maximum width is optional */
.wrap .grid,
.grid.wrap {
max-width: 978px;
margin: 0 auto;
}
/* Width classes also have shorthand versions numbered as fractions
* For example: for a grid unit 1/3 (one third) of the parent width,
* simply apply class="w-1-3" to the element. */
.grid .whole, .grid .w-1-1 { width: 100%; }
.grid .half, .grid .w-1-2 { width: 50%; }
.grid .one-third, .grid .w-1-3 { width: 33.3332%; }
.grid .two-thirds, .grid .w-2-3 { width: 66.6665%; }
.grid .one-quarter,
.grid .one-fourth, .grid .w-1-4 { width: 25%; }
.grid .three-quarters,
.grid .three-fourths, .grid .w-3-4 { width: 75%; }
.grid .one-fifth, .grid .w-1-5 { width: 20%; }
.grid .two-fifths, .grid .w-2-5 { width: 40%; }
.grid .three-fifths, .grid .w-3-5 { width: 60%; }
.grid .four-fifths, .grid .w-4-5 { width: 80%; }
.grid .golden-small, .grid .w-g-s { width: 38.2716%; } /* Golden section: smaller piece */
.grid .golden-large, .grid .w-g-l { width: 61.7283%; } /* Golden section: larger piece */
/* Clearfix after every .grid */
.grid {
*zoom: 1;
}
.grid:before, .grid:after {
display: table;
content: "";
line-height: 0;
}
.grid:after {
clear: both;
}
/* Utility classes */
.align-center { text-align: center; }
.align-left { text-align: left; }
.align-right { text-align: right; }
.pull-left { float: left; }
.pull-right { float: right; }
/* A property for a better rendering of images in units: in
this way bigger pictures are just resized if the unit
becomes smaller */
.unit img {
max-width: 100%;
}
/* Hide elements using this class by default */
.only-on-mobiles {
display: none !important;
}
/* Responsive Stuff */
@media screen and (max-width: 568px) {
/* Stack anything that isn't full-width on smaller screens
and doesn't provide the no-stacking-on-mobiles class */
.grid:not(.no-stacking-on-mobiles) > .unit {
width: 100% !important;
padding-left: 20px;
padding-right: 20px;
}
.unit .grid .unit {
padding-left: 0px;
padding-right: 0px;
}
/* Sometimes, you just want to be different on small screens */
.center-on-mobiles {
text-align: center !important;
}
.hide-on-mobiles {
display: none !important;
}
.only-on-mobiles {
display: block !important;
}
}
/* Expand the wrap a bit further on larger screens */
@media screen and (min-width: 1180px) {
.wider .grid,
.grid.wider {
max-width: 1180px;
margin: 0 auto;
}
}

View File

@@ -0,0 +1,95 @@
html, body {
box-sizing: border-box;
&:before, &:after {
box-sizing: border-box;
}
}
body {
font-family: $font-family-base;
line-height: $line-height-base;
font-size: $font-size-base;
color: $text-color;
font-weight: normal;
}
h1, h2, h3, h4, h5, h6 {
font-family: $headings-font-family;
font-weight: $headings-font-weight;
line-height: $headings-line-height;
margin: 0;
padding: 0;
}
h1 { font-size: 1.75em; }
h2 { font-size: 1.5em; }
h3 { font-size: 1.25em; }
h4 { font-size: 1.10em; }
h5 { font-size: 1em; }
h6 { font-size: .85em; }
nav {
margin: 1em 0;
ul {
list-style: none;
margin: 0;
padding: 0;
li {
display: inline-block;
margin-right: 1em;
margin-bottom: .25em;
}
}
}
a {
text-decoration: none;
color: $brand-primary;
&:hover, &:focus {
color: darken($brand-primary, 6.25%);
}
}
ul, ol {
margin-top: 0;
padding-top: 0;
padding-left: 2.5em;
}
p {
margin: 1em 0;
hyphens: auto;
&.lead {
font-size: 1.2em;
}
&:first-child {
margin-top: 0;
}
&:last-child {
margin-bottom: 0;
}
+ ul, + ol {
margin-top: -.75em;
}
}
dd {
margin-bottom: 1em;
margin-left: 0;
padding-left: 2.5em;
}
dt {
font-weight: 700;
}
blockquote {
margin: 0;
padding-left: 2.5em;
}

View File

@@ -0,0 +1,85 @@
/*
App reset by Ben Frain @benfrain / benfrain.com
Slightly modified by Bharani @bharani91 / github.com/bharani91
*/
/*Hat tip to @thierrykoblentz for this approach: https://css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice/ */
html {
box-sizing: border-box;
}
* {
user-select: none;
-webkit-tap-highlight-color: rgba(255,255,255,0);
-webkit-tap-highlight-color: transparent;
box-sizing: inherit;
}
*:before,
*:after {
box-sizing: inherit;
}
input[type],
[contenteditable] {
user-select: text;
}
body,
h1,
h2,
h3,
h4,
h5,
h6,
p {
margin: 0;
font-size: 1rem;
font-weight: 400;
}
a {
text-decoration: none;
color: inherit;
}
/*IMPORTANT: This removes the focus outline for most browsers. Be aware this is a backwards accessibilty step! Mozilla (i.e. Firefox) also adds a dotted outline around a tags and buttons when they receive tab focus which I haven't found an unhacky way of removing.*/
a:focus,
button:focus {
outline: 0;
}
button {
appearance: none;
background-color: transparent;
border: 0;
padding: 0;
}
input,
fieldset {
appearance: none;
border: 0;
padding: 0;
margin: 0;
min-width: 0;
font-size: 1rem;
font-family: inherit;
}
/*This switches the default outline off when an input receives focus (really important for users tabbing through with a keyboard) so ensure you put something decent in for your input focus instead!!*/
input:focus {
outline: 0;
}
img {
max-width: 100%;
display: block;
}
/*Removes the default focusring that Mozilla places on select items. From: http://stackoverflow.com/a/18853002/1147859
Ensure you set `#000` to the colour you want your text to appear */
select:-moz-focusring {
color: transparent;
text-shadow: 0 0 0 #000;
}

View File

@@ -0,0 +1,7 @@
.text-muted {
color: $text-secondary;
}
.text-center {
text-align: center;
}

View File

@@ -0,0 +1,17 @@
// Colors
$black: #111111;
$white: #ffffff;
$gray: #eeeeee;
$brand-primary: #4990E2;
$text-color: $black;
$text-secondary: #7A7A7A;
// Typography
$font-family-base: "Helvetica Neue", Helvetica, Arial, sans-serif;
$headings-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
$font-size-base: 16px;
$line-height-base: 1.5;
$headings-font-weight: 500;
$headings-line-height: 1.1;
$headings-color: $text-color;

38
src/styles/options.scss Normal file
View File

@@ -0,0 +1,38 @@
@import "modules/reset";
@import "modules/variables";
@import "modules/grid";
@import "modules/layout";
@import "modules/utilities";
.heading {
margin: 1em auto;
padding-bottom: 1em;
border-bottom: 1px solid #eee;
h1 + .lead {
margin-top: 0.2em;
}
}
.content {
min-height: 300px;
}
.option {
margin: 1em auto;
h5 {
margin-bottom: 1em;
}
.radio-group {
label {
display: block;
}
input[type="radio"] {
display: inline-block;
margin: 3px 5px;
}
}
}

88
src/styles/popup.scss Normal file
View File

@@ -0,0 +1,88 @@
@import "modules/reset";
@import "modules/variables";
@import "modules/layout";
body, html {
padding: 0;
margin: 0;
}
#app {
padding: 20px 20px;
background: $white;
}
footer {
color: $text-secondary;
text-align: right;
font-size: 0.8em;
a {
outline: none;
color: lighten($text-secondary, 10%);
&:hover {
color: $text-secondary;
}
}
}
.popup-content {
min-width: 220px;
min-height: 100px;
max-width: 350px;
}
.app-name {
font-size: 14px;
text-transform: uppercase;
color: $text-secondary;
text-align: center;
margin: 0 auto 1em auto;
padding: 0;
}
.site-description {
padding: 0.5em;
border: 1px solid $gray;
margin: 0;
h3 {
margin: 0;
padding: 0;
border-bottom: 1px solid $gray;
padding-bottom: 0.5em;
}
.description {
color: $text-secondary;
max-height: 100px;
font-size: 0.8em;
line-height: 1.2;
}
.url {
outline: none;
text-decoration: none;
line-height: 1.2;
font-size: 0.8em;
word-break: break-word;
display: block;
}
}
.action-container {
margin: 1em auto;
}
.btn {
background: none;
border: none;
display: inline-block;
cursor: pointer;
padding: 0.5em 1.5em;
background: $brand-primary;
color: $white;
font-weight: $headings-font-weight;
border-radius: 2px;
outline: none;
font-size: 1em;
}