├── .babelrc
├── .eslintrc
├── .gitignore
├── README.md
├── package.json
├── scripts.js
├── src
├── index.html
├── scripts.js
└── styles.scss
└── styles.css
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015"]
3 | }
4 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "eslint:recommended",
3 | "rules": {
4 | "indent": ["error", 2, { "SwitchCase": 1 }],
5 | "no-console": 0,
6 | "semi": ["error", "always"]
7 | },
8 | "globals": {
9 | "window": true,
10 | "define": true,
11 | "$": true
12 | },
13 | "env": {
14 | "node": true,
15 | "browser": true,
16 | "es6": true
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | npm-debug.log
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Caniuse Component
2 |
3 | Instant, up-to-date, and theme-able browser statistics for your presentations (so you don't have to update your slides the night before!)
4 |
5 | ### [Here is a Demo 😄](https://una.im/caniuse-component/)
6 |
7 | - customizable style based on a variable system
8 | - adaptive text color based on background [source](https://codepen.io/una/pen/oXgRYz)
9 | - automatic browser logos & caniuse data
10 | - not compatible with IE 6/7
11 |
12 | ## Usage
13 |
14 | ### Node Implementation
15 |
16 | Install via NPM: `npm install caniuse-component` -- include the js and css source.
17 |
18 | ### Reveal.js Implementation
19 |
20 | To use this with [Reveal.js](https://github.com/hakimel/reveal.js/), npm install, then apply this source as a plugin:
21 |
22 | ```
23 | Reveal.initialize({
24 | // setup things here:
25 | // ...
26 |
27 | // plugins here:
28 | dependencies: [
29 | { src: '../node_modules/caniuse-component/scripts.js', async: true },
30 | { src: '../node_modules/caniuse-component/styles.css' }
31 | ]
32 | });
33 | ```
34 |
35 | Then, include this element on your page:
36 |
37 | ```
38 |
42 | ```
43 |
44 | | name | function | usage | options |
45 | |--- |--- |--- |--- |
46 | | **id** | Applies styles to list | `id="caniuse--result-list"` | You only get one option unless you make your own |
47 | | **propName** | CSS Property Name | `data-propName="css-filters"` | See [Caniuse API](https://github.com/nyalab/caniuse-api) and [options](https://github.com/Fyrd/caniuse/tree/master/features-json) |
48 | | **browsers** | Browsers to check support from | `data-browsers="firefox chrome safari"` | `edge`, `chrome`, `safari`, `ie`, `firefox`, `opera` |
49 |
50 |
51 | ## Development & Contribution
52 |
53 | NPM scripts are used as the build system, so to develop, run: `npm run dev`. Consumable files are distributed in the root, and source files live within `/src`.
54 |
55 | To contribute: Please clone this down and submit a PR, or open an issue. 😘
56 |
57 | ## Credits
58 |
59 | - [Caniuse API](https://github.com/nyalab/caniuse-api)
60 | - [Browser Logos](https://github.com/alrra/browser-logos/)
61 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "caniuse-component",
3 | "version": "0.1.5",
4 | "description": "Up-to-date caniuse.com data for your slides",
5 | "main": "./scripts.js",
6 | "scripts": {
7 | "js": "watchify src/scripts.js -t babelify --outfile ./scripts.js",
8 | "compile-js": "babel src/scripts.js --out-file ./scripts.js",
9 | "styles": "node-sass -w src/ -o ./ --output-style compressed",
10 | "dev": "npm run js & npm run styles"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "git+https://github.com/una/caniuse-component.git"
15 | },
16 | "keywords": [
17 | "reveal.js",
18 | "presentation",
19 | "caniuse",
20 | "plugin"
21 | ],
22 | "author": "Una Kravets",
23 | "license": "MIT",
24 | "bugs": {
25 | "url": "https://github.com/una/caniuse-component/issues"
26 | },
27 | "homepage": "https://github.com/una/caniuse-component#readme",
28 | "dependencies": {
29 | "caniuse-api": "^2.0.0",
30 | "reveal.js": "^3.4.1"
31 | },
32 | "devDependencies": {
33 | "babel-cli": "^6.24.0",
34 | "babel-preset-es2015": "^6.24.0",
35 | "babelify": "^8.0.0",
36 | "watchify": "^3.9.0"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Caniuse Component
6 |
7 |
8 |
9 |
10 |
11 |
25 |
26 |
27 |
Browser Support: CSS Grid
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/scripts.js:
--------------------------------------------------------------------------------
1 | const caniuse = require('caniuse-api');
2 | const DOMContainer = document.querySelector('#caniuse--result-list');
3 | const defaultIcon = "";
4 |
5 | class ResultBlock {
6 | constructor(name) {
7 | this.name = name;
8 | }
9 |
10 | supportCall() {
11 | return caniuse.getSupport(this.name);
12 | }
13 |
14 | browserResults(browsers) {
15 |
16 | // iterate through each browser and show its support via caniuse info:
17 | // y: Since which browser version the feature is available
18 | // n: Up to which browser version the feature is unavailable
19 | // a: Up to which browser version the feature is partially supported
20 | // X: Up to which browser version the feature is prefixed
21 | for (let browser of browsers) {
22 | const browserName = browser;
23 | let returnedResult, supportLevel;
24 | let isPrefixed = false;
25 | const supportResults = this.supportCall()[browser];
26 |
27 | if (supportResults.y) { // its supported
28 | supportLevel = 'full';
29 | returnedResult = supportResults.y + '+';
30 |
31 | if (supportResults.a) {
32 | supportLevel = 'partial';
33 | }
34 |
35 | if (supportResults.x) {
36 | isPrefixed = true;
37 | }
38 | } else {
39 | supportLevel = 'none';
40 | returnedResult = 'no support';
41 | }
42 |
43 | this.buildBlock(browserName, returnedResult, supportLevel, isPrefixed);
44 | }
45 | }
46 |
47 | buildBlock(browserName, publishedResult, supportLevel, isPrefixed) {
48 | let prefixMsg;
49 |
50 | // IE rewrites
51 | if (browserName === 'ie') {
52 | browserName = 'internet-explorer';
53 | }
54 |
55 | // check if theres a level of support
56 | function supportText(supportLevel) {
57 | if (supportLevel != 'none') {
58 | return `${supportLevel}
`;
59 | } else return '';
60 | }
61 |
62 | // check if there is a prefix
63 | function prefixText(isPrefixed) {
64 | if (isPrefixed) {
65 | // these should be switch statements
66 | if (browserName === 'chrome' || browserName === 'safari') {
67 | prefixMsg = '-webkit-';
68 | }
69 | else if (browserName === 'firefox') {
70 | prefixMsg = '-moz-';
71 | }
72 | else if (browserName === 'edge' || browserName === 'ie') {
73 | prefixMsg = '-ms-';
74 | }
75 | else if (browserName === 'opera') {
76 | prefixMsg = '-o-';
77 | }
78 |
79 | return `${prefixMsg}
`;
80 | } else {
81 | if (supportLevel != 'none') {
82 | return `no prefix
`;
83 | } else {
84 | return '';
85 | }
86 | }
87 | }
88 |
89 | DOMContainer.innerHTML +=
90 | `
91 |
92 | ${browserName.replace(/-/g, ' ').replace(/(^|\s)[a-z]/g, (f) => {return f.toUpperCase();})}
93 | ${publishedResult}
94 | ${supportText(supportLevel)}
95 | ${prefixText(isPrefixed)}
96 | `;
97 | }
98 | }
99 |
100 | // Read the DOM and initiate based on data props
101 | document.onreadystatechange = () => {
102 | if (document.readyState === 'complete') {
103 | const name = DOMContainer.getAttribute('data-propName');
104 | const browsers = DOMContainer.getAttribute('data-browsers').split(' ');
105 | new ResultBlock(name, true).browserResults(browsers);
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/styles.scss:
--------------------------------------------------------------------------------
1 | $color--warn: #f1dc99; // partial support
2 | $color--success: #a2e9c1; // full support
3 | $color--error: #ffa5a5; // no support
4 | $color--text--light: #fff; // text color on dark backgrounds
5 | $color--text--dark: #000; // text color on light backgrounds
6 |
7 | $font__browser--size: 32px;
8 | $font__version--size: 24px;
9 | $font__meta--size: 18px;
10 | $border-radius: 2px;
11 | $li-margin: 10px;
12 | $icon-width: 120px;
13 |
14 | // Text Contrast Mixin
15 | // Determines font color based
16 | // on background color
17 | $contrast-settings: (
18 | 'light-color': $color--text--light,
19 | 'dark-color': $color--text--dark
20 | );
21 |
22 | @mixin contrast-me($bg-color) {
23 | @if lightness($bg-color) < 40% {
24 | color: map-get($contrast-settings, 'light-color');
25 | } @else {
26 | color: map-get($contrast-settings, 'dark-color');
27 | }
28 |
29 | background-color: $bg-color;
30 | }
31 |
32 | #caniuse--result-list {
33 | display: flex;
34 | flex-wrap: wrap;
35 | font-family: inherit;
36 | margin: 0;
37 | padding: 0;
38 |
39 | li {
40 | border-radius: $border-radius;
41 | flex: 1;
42 | list-style: none;
43 | margin: $li-margin;
44 | padding: $li-margin;
45 | text-align: center;
46 | }
47 |
48 | .caniuse {
49 | &--browser-img {
50 | height: $icon-width;
51 | margin: $li-margin * 2 auto 0;
52 | width: $icon-width;
53 | }
54 |
55 | &--browser-name {
56 | font-size: $font__browser--size;
57 | line-height: 1;
58 | }
59 |
60 | &--browser-results {
61 | font-size: $font__version--size;
62 | line-height: 0;
63 | }
64 |
65 | &--support-level {
66 | font-size: $font__meta--size;
67 | }
68 | }
69 |
70 | .support--partial {
71 | @include contrast-me($color--warn);
72 | }
73 |
74 | .support--full {
75 | @include contrast-me($color--success);
76 | }
77 |
78 | .support--none {
79 | @include contrast-me($color--error);
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/styles.css:
--------------------------------------------------------------------------------
1 | #caniuse--result-list{display:flex;flex-wrap:wrap;font-family:inherit;margin:0;padding:0}#caniuse--result-list li{border-radius:2px;flex:1;list-style:none;margin:10px;padding:10px;text-align:center}#caniuse--result-list .caniuse--browser-img{height:120px;margin:20px auto 0;width:120px}#caniuse--result-list .caniuse--browser-name{font-size:32px;line-height:1}#caniuse--result-list .caniuse--browser-results{font-size:24px;line-height:0}#caniuse--result-list .caniuse--support-level{font-size:18px}#caniuse--result-list .support--partial{color:#000;background-color:#f1dc99}#caniuse--result-list .support--full{color:#000;background-color:#a2e9c1}#caniuse--result-list .support--none{color:#000;background-color:#ffa5a5}
2 |
--------------------------------------------------------------------------------