├── .babelrc ├── .editorconfig ├── .travis.yml ├── test └── setup.js ├── .eslintrc ├── src ├── utilities │ └── buildScript.js ├── Typekit.spec.js └── Typekit.js ├── lib ├── utilities │ └── buildScript.js └── Typekit.js ├── package.json ├── .gitignore ├── .npmignore ├── README.md └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["env", "react"], 3 | } 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | indent_size = 2 7 | indent_style = space 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - node 5 | - 7 6 | - 6 7 | 8 | script: 9 | - npm run lint 10 | - npm test 11 | -------------------------------------------------------------------------------- /test/setup.js: -------------------------------------------------------------------------------- 1 | import { JSDOM } from 'jsdom'; 2 | 3 | const dom = new JSDOM(``); 4 | 5 | global.window = dom.window; 6 | global.document = dom.window.document; 7 | global.navigator = { userAgent: 'node.js' }; 8 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["eslint:recommended", "plugin:react/recommended"], 3 | "parserOptions": { 4 | "ecmaFeatures": { 5 | "experimentalObjectRestSpread": true, 6 | "jsx": true 7 | }, 8 | "sourceType": "module" 9 | }, 10 | "plugins": [ 11 | "react" 12 | ], 13 | "env": { 14 | "browser": true, 15 | "mocha": true, 16 | "node": true 17 | }, 18 | "rules": { 19 | "react/prop-types": 0 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/utilities/buildScript.js: -------------------------------------------------------------------------------- 1 | export default id => 2 | `(function(d) {var config = { kitId: '${id}', scriptTimeout: 3000, async: true }, h=d.documentElement,t=setTimeout(function(){h.className=h.className.replace(/\\bwf-loading\\b/g,"")+" wf-inactive";},config.scriptTimeout),tk=d.createElement("script"),f=false,s=d.getElementsByTagName("script")[0],a;h.className+=" wf-loading";tk.src='https://use.typekit.net/'+config.kitId+'.js';tk.async=true;tk.onload=tk.onreadystatechange=function(){a=this.readyState;if(f||a&&a!="complete"&&a!="loaded")return;f=true;clearTimeout(t);try{Typekit.load(config)}catch(e){}};s.parentNode.insertBefore(tk,s) })(document);`; 3 | -------------------------------------------------------------------------------- /src/Typekit.spec.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { expect } from 'chai'; 3 | import { mount } from 'enzyme'; 4 | import Typekit from './Typekit'; 5 | import buildScript from './utilities/buildScript'; 6 | 7 | describe('', () => { 8 | it('should output typekit script when kitId prop is present', () => { 9 | const kitId = 'abc123'; 10 | const wrapper = mount(); 11 | expect(wrapper.text()).to.equal(buildScript(kitId)); 12 | }); 13 | 14 | it('should output nothing when kitId prop is not present', () => { 15 | const wrapper = mount(); 16 | expect(wrapper.html()).to.equal(null); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /lib/utilities/buildScript.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | exports.default = function (id) { 8 | return "(function(d) {var config = { kitId: '" + id + "', scriptTimeout: 3000, async: true }, h=d.documentElement,t=setTimeout(function(){h.className=h.className.replace(/\\bwf-loading\\b/g,\"\")+\" wf-inactive\";},config.scriptTimeout),tk=d.createElement(\"script\"),f=false,s=d.getElementsByTagName(\"script\")[0],a;h.className+=\" wf-loading\";tk.src='https://use.typekit.net/'+config.kitId+'.js';tk.async=true;tk.onload=tk.onreadystatechange=function(){a=this.readyState;if(f||a&&a!=\"complete\"&&a!=\"loaded\")return;f=true;clearTimeout(t);try{Typekit.load(config)}catch(e){}};s.parentNode.insertBefore(tk,s) })(document);"; 9 | }; -------------------------------------------------------------------------------- /src/Typekit.js: -------------------------------------------------------------------------------- 1 | import intersection from 'lodash/intersection'; 2 | import split from 'lodash/split'; 3 | import PropTypes from 'prop-types'; 4 | import React, { Component } from 'react'; 5 | import buildScript from './utilities/buildScript'; 6 | 7 | class Typekit extends Component { 8 | componentDidMount() { 9 | // If typekit has not yet been executed, force it. 10 | const htmlClasses = split(document.querySelector('html').className, ' '); 11 | const typekitClasses = ['wf-loading', 'wf-active', 'wf-inactive']; 12 | const isLoaded = intersection(htmlClasses, typekitClasses).length > 0; 13 | if (this.script && !isLoaded) { 14 | const { kitId } = this.props; 15 | const script = document.createElement('script'); 16 | script.innerHTML = buildScript(kitId); 17 | this.script.parentNode.replaceChild(script, this.script); 18 | } 19 | } 20 | 21 | render() { 22 | const { kitId } = this.props; 23 | return this.props.kitId ? ( 24 |