├── .deployment ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .prettierrc ├── README.md ├── build ├── asset-manifest.json ├── examples │ └── exampleBibTex.bib ├── favicon.ico ├── images │ └── help │ │ ├── add-seed-papers.png │ │ ├── direction-switch.png │ │ ├── filtering.png │ │ ├── grow-network.png │ │ ├── highlight-node.png │ │ ├── recommended-papers.png │ │ ├── seed-papers.png │ │ └── view-switch.png ├── index.html ├── manifest.json ├── service-worker.js └── static │ ├── css │ ├── main.646c6520.css │ └── main.646c6520.css.map │ ├── js │ ├── main.34b57079.js │ └── main.34b57079.js.map │ └── media │ ├── geckologo.8b396eed.svg │ ├── network-icon.89f56a11.png │ └── new-logo.27ae6f13.svg ├── config ├── env.js ├── jest │ ├── cssTransform.js │ └── fileTransform.js ├── paths.js ├── polyfills.js ├── webpack.config.dev.js ├── webpack.config.prod.js └── webpackDevServer.config.js ├── jsconfig.json ├── package.json ├── public ├── examples │ └── exampleBibTex.bib ├── favicon.ico ├── images │ └── help │ │ ├── add-seed-papers.png │ │ ├── direction-switch.png │ │ ├── filtering.png │ │ ├── grow-network.png │ │ ├── highlight-node.png │ │ ├── recommended-papers.png │ │ ├── seed-papers.png │ │ └── view-switch.png ├── index.html └── manifest.json ├── scripts ├── build.js ├── start.js └── test.js ├── server ├── index.js └── services │ ├── mendeley │ ├── addDocuments.js │ ├── authenticate.js │ ├── getAllDocuments.js │ ├── getDocumentsInFolder.js │ ├── getFolders.js │ ├── lib │ │ ├── auth.js │ │ └── mendeley.js │ └── verify.js │ └── zotero │ ├── addItems.js │ ├── authenticate.js │ ├── getCollections.js │ ├── getItemsInCollection.js │ ├── lib │ ├── auth.js │ └── zotero.js │ ├── login.js │ └── verify.js ├── src ├── core │ ├── actions │ │ ├── DeletePaper │ │ │ └── index.js │ │ └── ToggleIrrelevant │ │ │ └── index.js │ ├── components │ │ ├── Action │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ ├── ButtonList │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ ├── DeleteButton │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ ├── Dropdown │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ ├── FilterOption │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ ├── GenericLeftPanel │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ ├── Icon │ │ │ └── index.js │ │ ├── Loader │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ ├── MetricLabel │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ ├── PaperCard │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ ├── PrimaryButton │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ ├── PrimarySquareButton │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ ├── SecondaryButton │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ ├── SecondarySquareButton │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ ├── SideBarButton │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ ├── Table │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ └── TextInput │ │ │ └── index.js │ ├── icons │ │ ├── DeleteIcon │ │ │ └── index.js │ │ ├── LinkoutIcon │ │ │ └── index.js │ │ ├── filter-icon.png │ │ ├── filter-icon.svg │ │ ├── help-icon.png │ │ ├── network-icon.png │ │ ├── network-icon.svg │ │ ├── recommended-icon.png │ │ ├── seed-icon.png │ │ ├── settings-icon.png │ │ ├── timeline-icon.png │ │ └── timeline-icon.svg │ ├── index.js │ ├── module-loader │ │ └── index.js │ ├── state │ │ ├── data.js │ │ ├── filters.js │ │ └── ui.js │ ├── styles.module.css │ ├── test.js │ └── ui │ │ ├── DownloadSVG │ │ ├── index.js │ │ └── styles.module.css │ │ ├── LeftPanel │ │ ├── PaperList │ │ │ └── index.js │ │ ├── RecommendedList │ │ │ └── index.js │ │ ├── SeedList │ │ │ └── index.js │ │ ├── Settings │ │ │ ├── FilterSettings │ │ │ │ ├── index.js │ │ │ │ └── styles.module.css │ │ │ ├── SortSettings │ │ │ │ ├── index.js │ │ │ │ └── styles.module.css │ │ │ └── index.js │ │ └── index.js │ │ ├── Logo │ │ ├── geckologo.svg │ │ ├── index.js │ │ └── styles.module.css │ │ ├── Modal │ │ ├── AddSeedsModal │ │ │ └── index.js │ │ ├── HelpModal │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ ├── StartModal │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ ├── ThankYouModal │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ ├── index.js │ │ └── styles.module.css │ │ ├── RightPanel │ │ ├── PaperInfoBox │ │ │ └── index.js │ │ ├── VisToggle │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ ├── index.js │ │ └── styles.module.css │ │ └── SideBar │ │ ├── index.js │ │ └── styles.module.css ├── data-modules │ ├── crossref │ │ └── index.js │ ├── index.js │ └── open-citations │ │ └── index.js ├── export-modules │ ├── bibtex │ │ └── index.js │ ├── index.js │ └── zotero │ │ └── index.js ├── import-modules │ ├── bibtex │ │ ├── UploadBibTexModal │ │ │ └── index.js │ │ └── index.js │ ├── crossref │ │ ├── SeedSearchModal │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ └── index.js │ ├── index.js │ ├── mendeley │ │ ├── MendeleyImportModal │ │ │ ├── index.js │ │ │ ├── styles.module.css │ │ │ ├── zotero-collection.png │ │ │ └── zotero-library.png │ │ └── index.js │ └── zotero │ │ ├── ZoteroImportModal │ │ ├── index.js │ │ ├── new-logo.svg │ │ ├── styles.module.css │ │ ├── zotero-collection.png │ │ └── zotero-library.png │ │ └── index.js ├── index.js ├── serviceWorker.js ├── third-party │ ├── bibtexParse.js │ ├── crossref.min.js │ ├── d3.v4.js │ └── js.cookie.min.js ├── utils │ └── index.js └── vis-modules │ ├── force-graph │ ├── components │ │ ├── ForceGraph │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ ├── ModeToggleKey │ │ │ ├── index.js │ │ │ └── styles.module.css │ │ └── ThresholdSlider │ │ │ ├── index.js │ │ │ └── styles.module.css │ └── index.js │ └── timeline │ ├── index.js │ └── styles.module.css ├── web.config └── yarn.lock /.deployment: -------------------------------------------------------------------------------- 1 | [config] 2 | SCM_DO_BUILD_DURING_DEPLOYMENT=true -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | public 3 | server.js 4 | src/third-party -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["react-app", "prettier"], 3 | "plugins": ["prettier"], 4 | "rules": { 5 | "prettier/prettier": ["error"], 6 | "jsx-a11y/href-no-hash": "off", 7 | "jsx-a11y/anchor-is-valid": ["warn", { "aspects": ["invalidHref"] }] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | #/build 11 | 12 | # misc 13 | .DS_Store 14 | .env 15 | .env.local 16 | .env.development.local 17 | .env.test.local 18 | .env.production.local 19 | 20 | npm-debug.log* 21 | yarn-debug.log* 22 | yarn-error.log* 23 | 24 | .vscode 25 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "singleQuote": true, 4 | "tabWidth": 2 5 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Welcome to Citation Gecko! 2 | 3 | [![Open Source Love](https://badges.frapsoft.com/os/v2/open-source.svg?v=103)](https://github.com/ellerbrock/open-source-badges/) 4 | [![MIT Licence](https://badges.frapsoft.com/os/mit/mit.svg?v=103)](https://opensource.org/licenses/mit-license.php) 5 | [![DOI](https://zenodo.org/badge/167792602.svg)](https://zenodo.org/badge/latestdoi/167792602) 6 | 7 | This is a tool that uses the citation relations between scientific papers to help researchers find interesting and relevant papers. 8 | 9 | The user specifies several 'seed' papers which define the specific area of the scientific landscape they are interested in. 10 | 11 | The tool then searches several databases to find the papers that cite or are cited-by the seed papers. 12 | 13 | Papers that are cited by a lot of the seed papers are likely to be important foundational papers in the field (or certainly worth being aware of at least). 14 | 15 | Papers that cite a lot of the seed papers are likely to be more recent papers in the same area that might be worth reading. 16 | 17 | The tool allows the user to view these highly connected papers either in a table or in the context of the network. 18 | 19 | ## Live demo 20 | 21 | [citationgecko.com](http://citationgecko.com) 22 | 23 | ## Running Citation Gecko locally 24 | 25 | 1. Clone the git repo: 26 | `git clone https://github.com/CitationGecko/gecko-react` 27 | 2. If you don't have it already install Node.js from https://nodejs.org/en/. 28 | 3. Install Yarn from https://yarnpkg.com/getting-started/install 29 | 4. Open a terminal and navigate to the repository folder. 30 | 5. Run `yarn` from the command line to install all the package dependencies. 31 | 6. Run `yarn run build` from the command line to build the app. 32 | 7. Run `yarn run start` to launch the server. 33 | 8. The application will be served to http://localhost:8000 34 | 35 | ## Instructions for use 36 | 37 | 1. Go to [citationgecko.com](http://citationgecko.com) or [localhost:8000](http://localhost:8000) if you're running application locally 38 | 2. Add some seed papers by clicking 'Add more seeds' button in the left-hand panel. 39 | 3. There are several ways of choosing seed papers to start with: 40 | 2. Upload a bibTex file (NOTE: currently only entries with a DOI will be added) 41 | - There is an example BibTex in the repository (public/examples/exampleBibTex.bib) which you can try importing as a test case. 42 | 3. Search for seed papers 43 | - Sends the query to the CrossRef API, can use title / author / keywords etc. 44 | - Choose which papers to add as seeds by clicking the Add buttons at the end of each row. 45 | 4. Import from Zotero 46 | - This will redirect you to Zotero in order to authenticate the app allow you to add papers in your zotero collections. 47 | 4. The seed papers added are listed in the left-hand panel and connections between them shown graphically in the right hand panel. 48 | 5. For a list of the papers connected to these seed papers click the icon with 3 dots in the side bar. 49 | 6. You can switch between viewing a graph showing only references of the seed papers and a graph showing only the papers that cite the seed papers by clicking the toggle between 'Papers Cited-By Seed Papers' and 'Papers Citing Seed Papers' that also acts as a key. 50 | 7. If one of the connected papers seems highly relevant you can add it as a seed paper either from the list view or network view, expanding the network in order to uncover more papers. 51 | 52 | ## Citing CitationGecko 53 | 54 | To cite CitationGecko use the following details: 55 | 56 | Author: Barnabas James Walker 57 | 58 | Title: CitationGecko 59 | 60 | DOI: https://doi.org/10.5281/zenodo.7068284 61 | 62 | An example format may be: 63 | 64 | Walker. B (2022) CitationGecko [Software] https://doi.org/10.5281/zenodo.7068284 65 | -------------------------------------------------------------------------------- /build/asset-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "main.css": "static/css/main.646c6520.css", 3 | "main.css.map": "static/css/main.646c6520.css.map", 4 | "main.js": "static/js/main.34b57079.js", 5 | "main.js.map": "static/js/main.34b57079.js.map", 6 | "static/media/geckologo.svg": "static/media/geckologo.8b396eed.svg", 7 | "static/media/network-icon.png": "static/media/network-icon.89f56a11.png", 8 | "static/media/new-logo.svg": "static/media/new-logo.27ae6f13.svg" 9 | } -------------------------------------------------------------------------------- /build/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CitationGecko/gecko-react/e4133f99ddd3831a9da5162c8f60654e37e3c1b0/build/favicon.ico -------------------------------------------------------------------------------- /build/images/help/add-seed-papers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CitationGecko/gecko-react/e4133f99ddd3831a9da5162c8f60654e37e3c1b0/build/images/help/add-seed-papers.png -------------------------------------------------------------------------------- /build/images/help/direction-switch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CitationGecko/gecko-react/e4133f99ddd3831a9da5162c8f60654e37e3c1b0/build/images/help/direction-switch.png -------------------------------------------------------------------------------- /build/images/help/filtering.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CitationGecko/gecko-react/e4133f99ddd3831a9da5162c8f60654e37e3c1b0/build/images/help/filtering.png -------------------------------------------------------------------------------- /build/images/help/grow-network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CitationGecko/gecko-react/e4133f99ddd3831a9da5162c8f60654e37e3c1b0/build/images/help/grow-network.png -------------------------------------------------------------------------------- /build/images/help/highlight-node.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CitationGecko/gecko-react/e4133f99ddd3831a9da5162c8f60654e37e3c1b0/build/images/help/highlight-node.png -------------------------------------------------------------------------------- /build/images/help/recommended-papers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CitationGecko/gecko-react/e4133f99ddd3831a9da5162c8f60654e37e3c1b0/build/images/help/recommended-papers.png -------------------------------------------------------------------------------- /build/images/help/seed-papers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CitationGecko/gecko-react/e4133f99ddd3831a9da5162c8f60654e37e3c1b0/build/images/help/seed-papers.png -------------------------------------------------------------------------------- /build/images/help/view-switch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CitationGecko/gecko-react/e4133f99ddd3831a9da5162c8f60654e37e3c1b0/build/images/help/view-switch.png -------------------------------------------------------------------------------- /build/index.html: -------------------------------------------------------------------------------- 1 | Citation Gecko
-------------------------------------------------------------------------------- /build/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "CitationGecko", 3 | "name": "Citation Gecko", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /build/service-worker.js: -------------------------------------------------------------------------------- 1 | "use strict";var precacheConfig=[["/index.html","6183f28a6c62d4e7f9bbd9c79d1c7cde"],["/static/css/main.646c6520.css","106603706d25fea87f765600c277a23f"],["/static/js/main.34b57079.js","cd829c0b9381ca55628b19cc81f063fa"],["/static/media/geckologo.8b396eed.svg","8b396eed633c20952fede005e0cffbe6"],["/static/media/network-icon.89f56a11.png","89f56a118a996049d3d7cfacf49ecc75"],["/static/media/new-logo.27ae6f13.svg","27ae6f1315cf82c18ab8966ee5514e7b"]],cacheName="sw-precache-v3-sw-precache-webpack-plugin-"+(self.registration?self.registration.scope:""),ignoreUrlParametersMatching=[/^utm_/],addDirectoryIndex=function(e,t){var n=new URL(e);return"/"===n.pathname.slice(-1)&&(n.pathname+=t),n.toString()},cleanResponse=function(t){return t.redirected?("body"in t?Promise.resolve(t.body):t.blob()).then(function(e){return new Response(e,{headers:t.headers,status:t.status,statusText:t.statusText})}):Promise.resolve(t)},createCacheKey=function(e,t,n,r){var a=new URL(e);return r&&a.pathname.match(r)||(a.search+=(a.search?"&":"")+encodeURIComponent(t)+"="+encodeURIComponent(n)),a.toString()},isPathWhitelisted=function(e,t){if(0===e.length)return!0;var n=new URL(t).pathname;return e.some(function(e){return n.match(e)})},stripIgnoredUrlParameters=function(e,n){var t=new URL(e);return t.hash="",t.search=t.search.slice(1).split("&").map(function(e){return e.split("=")}).filter(function(t){return n.every(function(e){return!e.test(t[0])})}).map(function(e){return e.join("=")}).join("&"),t.toString()},hashParamName="_sw-precache",urlsToCacheKeys=new Map(precacheConfig.map(function(e){var t=e[0],n=e[1],r=new URL(t,self.location),a=createCacheKey(r,hashParamName,n,/\.\w{8}\./);return[r.toString(),a]}));function setOfCachedUrls(e){return e.keys().then(function(e){return e.map(function(e){return e.url})}).then(function(e){return new Set(e)})}self.addEventListener("install",function(e){e.waitUntil(caches.open(cacheName).then(function(r){return setOfCachedUrls(r).then(function(n){return Promise.all(Array.from(urlsToCacheKeys.values()).map(function(t){if(!n.has(t)){var e=new Request(t,{credentials:"same-origin"});return fetch(e).then(function(e){if(!e.ok)throw new Error("Request for "+t+" returned a response with status "+e.status);return cleanResponse(e).then(function(e){return r.put(t,e)})})}}))})}).then(function(){return self.skipWaiting()}))}),self.addEventListener("activate",function(e){var n=new Set(urlsToCacheKeys.values());e.waitUntil(caches.open(cacheName).then(function(t){return t.keys().then(function(e){return Promise.all(e.map(function(e){if(!n.has(e.url))return t.delete(e)}))})}).then(function(){return self.clients.claim()}))}),self.addEventListener("fetch",function(t){if("GET"===t.request.method){var e,n=stripIgnoredUrlParameters(t.request.url,ignoreUrlParametersMatching),r="index.html";(e=urlsToCacheKeys.has(n))||(n=addDirectoryIndex(n,r),e=urlsToCacheKeys.has(n));var a="/index.html";!e&&"navigate"===t.request.mode&&isPathWhitelisted(["^(?!\\/services).*"],t.request.url)&&(n=new URL(a,self.location).toString(),e=urlsToCacheKeys.has(n)),e&&t.respondWith(caches.open(cacheName).then(function(e){return e.match(urlsToCacheKeys.get(n)).then(function(e){if(e)return e;throw Error("The cached response that was expected is missing.")})}).catch(function(e){return console.warn('Couldn\'t serve response for "%s" from cache: %O',t.request.url,e),fetch(t.request)}))}}); -------------------------------------------------------------------------------- /build/static/media/network-icon.89f56a11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CitationGecko/gecko-react/e4133f99ddd3831a9da5162c8f60654e37e3c1b0/build/static/media/network-icon.89f56a11.png -------------------------------------------------------------------------------- /build/static/media/new-logo.27ae6f13.svg: -------------------------------------------------------------------------------- 1 | 2 | Zotero 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /config/env.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const paths = require('./paths'); 6 | 7 | // Make sure that including paths.js after env.js will read .env variables. 8 | delete require.cache[require.resolve('./paths')]; 9 | 10 | const NODE_ENV = process.env.NODE_ENV; 11 | if (!NODE_ENV) { 12 | throw new Error('The NODE_ENV environment variable is required but was not specified.'); 13 | } 14 | 15 | // https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use 16 | var dotenvFiles = [ 17 | `${paths.dotenv}.${NODE_ENV}.local`, 18 | `${paths.dotenv}.${NODE_ENV}`, 19 | // Don't include `.env.local` for `test` environment 20 | // since normally you expect tests to produce the same 21 | // results for everyone 22 | NODE_ENV !== 'test' && `${paths.dotenv}.local`, 23 | paths.dotenv 24 | ].filter(Boolean); 25 | 26 | // Load environment variables from .env* files. Suppress warnings using silent 27 | // if this file is missing. dotenv will never modify any environment variables 28 | // that have already been set. Variable expansion is supported in .env files. 29 | // https://github.com/motdotla/dotenv 30 | // https://github.com/motdotla/dotenv-expand 31 | dotenvFiles.forEach(dotenvFile => { 32 | if (fs.existsSync(dotenvFile)) { 33 | require('dotenv-expand')( 34 | require('dotenv').config({ 35 | path: dotenvFile 36 | }) 37 | ); 38 | } 39 | }); 40 | 41 | // We support resolving modules according to `NODE_PATH`. 42 | // This lets you use absolute paths in imports inside large monorepos: 43 | // https://github.com/facebookincubator/create-react-app/issues/253. 44 | // It works similar to `NODE_PATH` in Node itself: 45 | // https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders 46 | // Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored. 47 | // Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims. 48 | // https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421 49 | // We also resolve them to make sure all tools using them work consistently. 50 | const appDirectory = fs.realpathSync(process.cwd()); 51 | process.env.NODE_PATH = (process.env.NODE_PATH || '') 52 | .split(path.delimiter) 53 | .filter(folder => folder && !path.isAbsolute(folder)) 54 | .map(folder => path.resolve(appDirectory, folder)) 55 | .join(path.delimiter); 56 | 57 | // Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be 58 | // injected into the application via DefinePlugin in Webpack configuration. 59 | const REACT_APP = /^REACT_APP_/i; 60 | 61 | function getClientEnvironment(publicUrl) { 62 | const raw = Object.keys(process.env) 63 | .filter(key => REACT_APP.test(key)) 64 | .reduce( 65 | (env, key) => { 66 | env[key] = process.env[key]; 67 | return env; 68 | }, 69 | { 70 | // Useful for determining whether we’re running in production mode. 71 | // Most importantly, it switches React into the correct mode. 72 | NODE_ENV: process.env.NODE_ENV || 'development', 73 | // Useful for resolving the correct path to static assets in `public`. 74 | // For example, . 75 | // This should only be used as an escape hatch. Normally you would put 76 | // images into the `src` and `import` them in code to get their paths. 77 | PUBLIC_URL: publicUrl 78 | } 79 | ); 80 | // Stringify all values so we can feed into Webpack DefinePlugin 81 | const stringified = { 82 | 'process.env': Object.keys(raw).reduce((env, key) => { 83 | env[key] = JSON.stringify(raw[key]); 84 | return env; 85 | }, {}) 86 | }; 87 | 88 | return { raw, stringified }; 89 | } 90 | 91 | module.exports = getClientEnvironment; 92 | -------------------------------------------------------------------------------- /config/jest/cssTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // This is a custom Jest transformer turning style imports into empty objects. 4 | // http://facebook.github.io/jest/docs/en/webpack.html 5 | 6 | module.exports = { 7 | process() { 8 | return 'module.exports = {};'; 9 | }, 10 | getCacheKey() { 11 | // The output is always the same. 12 | return 'cssTransform'; 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /config/jest/fileTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | 5 | // This is a custom Jest transformer turning file imports into filenames. 6 | // http://facebook.github.io/jest/docs/en/webpack.html 7 | 8 | module.exports = { 9 | process(src, filename) { 10 | return `module.exports = ${JSON.stringify(path.basename(filename))};`; 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /config/paths.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const fs = require('fs'); 5 | const url = require('url'); 6 | 7 | // Make sure any symlinks in the project folder are resolved: 8 | // https://github.com/facebookincubator/create-react-app/issues/637 9 | const appDirectory = fs.realpathSync(process.cwd()); 10 | const resolveApp = relativePath => path.resolve(appDirectory, relativePath); 11 | 12 | const envPublicUrl = process.env.PUBLIC_URL; 13 | 14 | function ensureSlash(path, needsSlash) { 15 | const hasSlash = path.endsWith('/'); 16 | if (hasSlash && !needsSlash) { 17 | return path.substr(path, path.length - 1); 18 | } else if (!hasSlash && needsSlash) { 19 | return `${path}/`; 20 | } else { 21 | return path; 22 | } 23 | } 24 | 25 | const getPublicUrl = appPackageJson => envPublicUrl || require(appPackageJson).homepage; 26 | 27 | // We use `PUBLIC_URL` environment variable or "homepage" field to infer 28 | // "public path" at which the app is served. 29 | // Webpack needs to know it to put the right