├── .gitignore ├── README.md ├── config ├── env.js ├── getHttpsConfig.js ├── jest │ ├── babelTransform.js │ ├── cssTransform.js │ └── fileTransform.js ├── modules.js ├── paths.js ├── webpack.config.js ├── webpack │ └── persistentCache │ │ └── createEnvironmentHash.js └── webpackDevServer.config.js ├── package-lock.json ├── package.json ├── public ├── bibliography.bib ├── data │ ├── neuron-explanations-compressed.json │ ├── neurons-kitkat.json │ ├── neurons-leprechaun.json │ ├── neurons-spacemanandy.json │ ├── neurons-vaccine.json │ ├── nmf-kitkat.json │ ├── nmf-leprechaun.json │ ├── nmf-spacemanandy.json │ └── nmf-vaccine.json ├── distill-template.v2.js ├── favicon.ico ├── images │ ├── ablation_js_loss_vs_corr_coef_binned_fill_between_use_log_False_show_sem_True_random.jpg │ ├── ablation_js_loss_vs_corr_coef_binned_fill_between_use_log_False_show_sem_True_top_and_random.jpg │ ├── algostep1.png │ ├── algostep2.png │ ├── algostep3.png │ ├── dirfinding-component-truncation.png │ ├── higher_preferred_rate_by_score_diff.png │ ├── layerwise_score_errorbars_next_token_all.png │ ├── layerwise_score_errorbars_next_token_random.png │ ├── layerwise_score_errorbars_token_linear_all.png │ ├── layerwise_score_errorbars_token_linear_random.png │ ├── layerwise_score_errorbars_token_lookup_all.png │ ├── layerwise_score_errorbars_token_lookup_random.png │ ├── neuron_puzzle_example_1.png │ ├── neuron_puzzle_example_2.png │ ├── neuron_puzzle_example_3.png │ ├── neuron_puzzle_example_4.png │ ├── patternbreak.png │ ├── real_vs_simulated_activations_0_1295_top_and_random.jpg │ ├── real_vs_simulated_activations_15_5473_top_and_random.jpg │ ├── real_vs_simulated_activations_5_2764_top_and_random.jpg │ ├── real_vs_simulated_activations_6_1746_top_and_random.jpg │ ├── revision-and-baselines.all.png │ └── revision-and-baselines.random.png ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json ├── plots │ ├── ablation_js_loss_vs_corr_coef_binned_fill_between_use_log_False_show_sem_True_top_and_random.jpg │ ├── activation_function_explainability.all.png │ ├── activation_function_explainability.random_only.png │ ├── data_scaling.all.png │ ├── data_scaling.random_only.png │ ├── dirfinding-cos.png │ ├── dirfinding-scores.png │ ├── explainer_model_scaling.all.png │ ├── explainer_model_scaling.random_only.png │ ├── explanation_score_hists │ │ ├── layer_0.corr.all.png │ │ ├── layer_0.corr.random_only.png │ │ ├── layer_1.corr.all.png │ │ ├── layer_1.corr.random_only.png │ │ ├── layer_10.corr.all.png │ │ ├── layer_10.corr.random_only.png │ │ ├── layer_11.corr.all.png │ │ ├── layer_11.corr.random_only.png │ │ ├── layer_12.corr.all.png │ │ ├── layer_12.corr.random_only.png │ │ ├── layer_13.corr.all.png │ │ ├── layer_13.corr.random_only.png │ │ ├── layer_14.corr.all.png │ │ ├── layer_14.corr.random_only.png │ │ ├── layer_15.corr.all.png │ │ ├── layer_15.corr.random_only.png │ │ ├── layer_16.corr.all.png │ │ ├── layer_16.corr.random_only.png │ │ ├── layer_17.corr.all.png │ │ ├── layer_17.corr.random_only.png │ │ ├── layer_18.corr.all.png │ │ ├── layer_18.corr.random_only.png │ │ ├── layer_19.corr.all.png │ │ ├── layer_19.corr.random_only.png │ │ ├── layer_2.corr.all.png │ │ ├── layer_2.corr.random_only.png │ │ ├── layer_20.corr.all.png │ │ ├── layer_20.corr.random_only.png │ │ ├── layer_21.corr.all.png │ │ ├── layer_21.corr.random_only.png │ │ ├── layer_22.corr.all.png │ │ ├── layer_22.corr.random_only.png │ │ ├── layer_23.corr.all.png │ │ ├── layer_23.corr.random_only.png │ │ ├── layer_24.corr.all.png │ │ ├── layer_24.corr.random_only.png │ │ ├── layer_25.corr.all.png │ │ ├── layer_25.corr.random_only.png │ │ ├── layer_26.corr.all.png │ │ ├── layer_26.corr.random_only.png │ │ ├── layer_27.corr.all.png │ │ ├── layer_27.corr.random_only.png │ │ ├── layer_28.corr.all.png │ │ ├── layer_28.corr.random_only.png │ │ ├── layer_29.corr.all.png │ │ ├── layer_29.corr.random_only.png │ │ ├── layer_3.corr.all.png │ │ ├── layer_3.corr.random_only.png │ │ ├── layer_30.corr.all.png │ │ ├── layer_30.corr.random_only.png │ │ ├── layer_31.corr.all.png │ │ ├── layer_31.corr.random_only.png │ │ ├── layer_32.corr.all.png │ │ ├── layer_32.corr.random_only.png │ │ ├── layer_33.corr.all.png │ │ ├── layer_33.corr.random_only.png │ │ ├── layer_34.corr.all.png │ │ ├── layer_34.corr.random_only.png │ │ ├── layer_35.corr.all.png │ │ ├── layer_35.corr.random_only.png │ │ ├── layer_36.corr.all.png │ │ ├── layer_36.corr.random_only.png │ │ ├── layer_37.corr.all.png │ │ ├── layer_37.corr.random_only.png │ │ ├── layer_38.corr.all.png │ │ ├── layer_38.corr.random_only.png │ │ ├── layer_39.corr.all.png │ │ ├── layer_39.corr.random_only.png │ │ ├── layer_4.corr.all.png │ │ ├── layer_4.corr.random_only.png │ │ ├── layer_40.corr.all.png │ │ ├── layer_40.corr.random_only.png │ │ ├── layer_41.corr.all.png │ │ ├── layer_41.corr.random_only.png │ │ ├── layer_42.corr.all.png │ │ ├── layer_42.corr.random_only.png │ │ ├── layer_43.corr.all.png │ │ ├── layer_43.corr.random_only.png │ │ ├── layer_44.corr.all.png │ │ ├── layer_44.corr.random_only.png │ │ ├── layer_45.corr.all.png │ │ ├── layer_45.corr.random_only.png │ │ ├── layer_46.corr.all.png │ │ ├── layer_46.corr.random_only.png │ │ ├── layer_47.corr.all.png │ │ ├── layer_47.corr.random_only.png │ │ ├── layer_5.corr.all.png │ │ ├── layer_5.corr.random_only.png │ │ ├── layer_6.corr.all.png │ │ ├── layer_6.corr.random_only.png │ │ ├── layer_7.corr.all.png │ │ ├── layer_7.corr.random_only.png │ │ ├── layer_8.corr.all.png │ │ ├── layer_8.corr.random_only.png │ │ ├── layer_9.corr.all.png │ │ └── layer_9.corr.random_only.png │ ├── quantile_scaling.png │ ├── revision-and-baselines.all.png │ ├── revision.top_and_random.png │ ├── simulator_model_scaling.all.png │ ├── simulator_model_scaling.human.png │ ├── simulator_model_scaling.random_only.png │ ├── subject_model_scaling.all.png │ ├── subject_model_scaling.random_only.png │ ├── subject_model_scaling_layers.all.png │ └── subject_model_scaling_layers.random_only.png ├── robots.txt ├── test.html └── third-party │ ├── katex.min.css │ └── katex.min.js ├── scripts ├── build.js ├── start.js └── test.js └── src ├── App.css ├── App.js ├── App.test.js ├── components ├── hidden.js ├── tokenheatmap.js └── ui.js ├── content.mdx ├── diagrams ├── carousel.js ├── carousel_neurons.json ├── decomposedSentences │ └── index.js ├── dirfinding_compare.js ├── equation.js ├── layer_slider.js ├── neuron_carousel.js ├── prompts.js ├── revision_scoring_toggle.js └── scoring_toggle.js ├── index.css ├── index.js ├── logo.svg ├── paper.jsx ├── reportWebVitals.js └── setupTests.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional stylelint cache 58 | .stylelintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variable files 76 | .env 77 | .env.development.local 78 | .env.test.local 79 | .env.production.local 80 | .env.local 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | .parcel-cache 85 | 86 | # Next.js build output 87 | .next 88 | out 89 | 90 | # Nuxt.js build / generate output 91 | .nuxt 92 | dist 93 | 94 | # Gatsby files 95 | .cache/ 96 | # Comment in the public line in if your project uses Gatsby and not Next.js 97 | # https://nextjs.org/blog/next-9-1#public-directory-support 98 | # public 99 | 100 | # vuepress build output 101 | .vuepress/dist 102 | 103 | # vuepress v2.x temp and cache directory 104 | .temp 105 | .cache 106 | 107 | # Docusaurus cache and generated files 108 | .docusaurus 109 | 110 | # Serverless directories 111 | .serverless/ 112 | 113 | # FuseBox cache 114 | .fusebox/ 115 | 116 | # DynamoDB Local files 117 | .dynamodb/ 118 | 119 | # TernJS port file 120 | .tern-port 121 | 122 | # Stores VSCode versions used for testing VSCode extensions 123 | .vscode-test 124 | 125 | # yarn v2 126 | .yarn/cache 127 | .yarn/unplugged 128 | .yarn/build-state.yml 129 | .yarn/install-state.gz 130 | .pnp.* 131 | .DS_Store 132 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Language models can explain neurons in language models 2 | 3 | The source code of 4 | https://openaipublic.blob.core.windows.net/neuron-explainer/paper/index.html 5 | 6 | # Setup 7 | 8 | In the project directory, you can run: 9 | 10 | ### `npm install` 11 | 12 | ### `npm start` 13 | 14 | Runs the app in the development mode.\ 15 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser. 16 | -------------------------------------------------------------------------------- /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( 13 | 'The NODE_ENV environment variable is required but was not specified.' 14 | ); 15 | } 16 | 17 | // https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use 18 | const dotenvFiles = [ 19 | `${paths.dotenv}.${NODE_ENV}.local`, 20 | // Don't include `.env.local` for `test` environment 21 | // since normally you expect tests to produce the same 22 | // results for everyone 23 | NODE_ENV !== 'test' && `${paths.dotenv}.local`, 24 | `${paths.dotenv}.${NODE_ENV}`, 25 | paths.dotenv, 26 | ].filter(Boolean); 27 | 28 | // Load environment variables from .env* files. Suppress warnings using silent 29 | // if this file is missing. dotenv will never modify any environment variables 30 | // that have already been set. Variable expansion is supported in .env files. 31 | // https://github.com/motdotla/dotenv 32 | // https://github.com/motdotla/dotenv-expand 33 | dotenvFiles.forEach(dotenvFile => { 34 | if (fs.existsSync(dotenvFile)) { 35 | require('dotenv-expand')( 36 | require('dotenv').config({ 37 | path: dotenvFile, 38 | }) 39 | ); 40 | } 41 | }); 42 | 43 | // We support resolving modules according to `NODE_PATH`. 44 | // This lets you use absolute paths in imports inside large monorepos: 45 | // https://github.com/facebook/create-react-app/issues/253. 46 | // It works similar to `NODE_PATH` in Node itself: 47 | // https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders 48 | // Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored. 49 | // Otherwise, we risk importing Node.js core modules into an app instead of webpack shims. 50 | // https://github.com/facebook/create-react-app/issues/1023#issuecomment-265344421 51 | // We also resolve them to make sure all tools using them work consistently. 52 | const appDirectory = fs.realpathSync(process.cwd()); 53 | process.env.NODE_PATH = (process.env.NODE_PATH || '') 54 | .split(path.delimiter) 55 | .filter(folder => folder && !path.isAbsolute(folder)) 56 | .map(folder => path.resolve(appDirectory, folder)) 57 | .join(path.delimiter); 58 | 59 | // Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be 60 | // injected into the application via DefinePlugin in webpack configuration. 61 | const REACT_APP = /^REACT_APP_/i; 62 | 63 | function getClientEnvironment(publicUrl) { 64 | const raw = Object.keys(process.env) 65 | .filter(key => REACT_APP.test(key)) 66 | .reduce( 67 | (env, key) => { 68 | env[key] = process.env[key]; 69 | return env; 70 | }, 71 | { 72 | // Useful for determining whether we’re running in production mode. 73 | // Most importantly, it switches React into the correct mode. 74 | NODE_ENV: process.env.NODE_ENV || 'development', 75 | // Useful for resolving the correct path to static assets in `public`. 76 | // For example, . 77 | // This should only be used as an escape hatch. Normally you would put 78 | // images into the `src` and `import` them in code to get their paths. 79 | PUBLIC_URL: publicUrl, 80 | // We support configuring the sockjs pathname during development. 81 | // These settings let a developer run multiple simultaneous projects. 82 | // They are used as the connection `hostname`, `pathname` and `port` 83 | // in webpackHotDevClient. They are used as the `sockHost`, `sockPath` 84 | // and `sockPort` options in webpack-dev-server. 85 | WDS_SOCKET_HOST: process.env.WDS_SOCKET_HOST, 86 | WDS_SOCKET_PATH: process.env.WDS_SOCKET_PATH, 87 | WDS_SOCKET_PORT: process.env.WDS_SOCKET_PORT, 88 | // Whether or not react-refresh is enabled. 89 | // It is defined here so it is available in the webpackHotDevClient. 90 | FAST_REFRESH: process.env.FAST_REFRESH !== 'false', 91 | } 92 | ); 93 | // Stringify all values so we can feed into webpack DefinePlugin 94 | const stringified = { 95 | 'process.env': Object.keys(raw).reduce((env, key) => { 96 | env[key] = JSON.stringify(raw[key]); 97 | return env; 98 | }, {}), 99 | }; 100 | 101 | return { raw, stringified }; 102 | } 103 | 104 | module.exports = getClientEnvironment; 105 | -------------------------------------------------------------------------------- /config/getHttpsConfig.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const crypto = require('crypto'); 6 | const chalk = require('react-dev-utils/chalk'); 7 | const paths = require('./paths'); 8 | 9 | // Ensure the certificate and key provided are valid and if not 10 | // throw an easy to debug error 11 | function validateKeyAndCerts({ cert, key, keyFile, crtFile }) { 12 | let encrypted; 13 | try { 14 | // publicEncrypt will throw an error with an invalid cert 15 | encrypted = crypto.publicEncrypt(cert, Buffer.from('test')); 16 | } catch (err) { 17 | throw new Error( 18 | `The certificate "${chalk.yellow(crtFile)}" is invalid.\n${err.message}` 19 | ); 20 | } 21 | 22 | try { 23 | // privateDecrypt will throw an error with an invalid key 24 | crypto.privateDecrypt(key, encrypted); 25 | } catch (err) { 26 | throw new Error( 27 | `The certificate key "${chalk.yellow(keyFile)}" is invalid.\n${ 28 | err.message 29 | }` 30 | ); 31 | } 32 | } 33 | 34 | // Read file and throw an error if it doesn't exist 35 | function readEnvFile(file, type) { 36 | if (!fs.existsSync(file)) { 37 | throw new Error( 38 | `You specified ${chalk.cyan( 39 | type 40 | )} in your env, but the file "${chalk.yellow(file)}" can't be found.` 41 | ); 42 | } 43 | return fs.readFileSync(file); 44 | } 45 | 46 | // Get the https config 47 | // Return cert files if provided in env, otherwise just true or false 48 | function getHttpsConfig() { 49 | const { SSL_CRT_FILE, SSL_KEY_FILE, HTTPS } = process.env; 50 | const isHttps = HTTPS === 'true'; 51 | 52 | if (isHttps && SSL_CRT_FILE && SSL_KEY_FILE) { 53 | const crtFile = path.resolve(paths.appPath, SSL_CRT_FILE); 54 | const keyFile = path.resolve(paths.appPath, SSL_KEY_FILE); 55 | const config = { 56 | cert: readEnvFile(crtFile, 'SSL_CRT_FILE'), 57 | key: readEnvFile(keyFile, 'SSL_KEY_FILE'), 58 | }; 59 | 60 | validateKeyAndCerts({ ...config, keyFile, crtFile }); 61 | return config; 62 | } 63 | return isHttps; 64 | } 65 | 66 | module.exports = getHttpsConfig; 67 | -------------------------------------------------------------------------------- /config/jest/babelTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const babelJest = require('babel-jest').default; 4 | 5 | const hasJsxRuntime = (() => { 6 | if (process.env.DISABLE_NEW_JSX_TRANSFORM === 'true') { 7 | return false; 8 | } 9 | 10 | try { 11 | require.resolve('react/jsx-runtime'); 12 | return true; 13 | } catch (e) { 14 | return false; 15 | } 16 | })(); 17 | 18 | module.exports = babelJest.createTransformer({ 19 | presets: [ 20 | [ 21 | require.resolve('babel-preset-react-app'), 22 | { 23 | runtime: hasJsxRuntime ? 'automatic' : 'classic', 24 | }, 25 | ], 26 | ], 27 | babelrc: false, 28 | configFile: false, 29 | }); 30 | -------------------------------------------------------------------------------- /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 | const camelcase = require('camelcase'); 5 | 6 | // This is a custom Jest transformer turning file imports into filenames. 7 | // http://facebook.github.io/jest/docs/en/webpack.html 8 | 9 | module.exports = { 10 | process(src, filename) { 11 | const assetFilename = JSON.stringify(path.basename(filename)); 12 | 13 | if (filename.match(/\.svg$/)) { 14 | // Based on how SVGR generates a component name: 15 | // https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6 16 | const pascalCaseFilename = camelcase(path.parse(filename).name, { 17 | pascalCase: true, 18 | }); 19 | const componentName = `Svg${pascalCaseFilename}`; 20 | return `const React = require('react'); 21 | module.exports = { 22 | __esModule: true, 23 | default: ${assetFilename}, 24 | ReactComponent: React.forwardRef(function ${componentName}(props, ref) { 25 | return { 26 | $$typeof: Symbol.for('react.element'), 27 | type: 'svg', 28 | ref: ref, 29 | key: null, 30 | props: Object.assign({}, props, { 31 | children: ${assetFilename} 32 | }) 33 | }; 34 | }), 35 | };`; 36 | } 37 | 38 | return `module.exports = ${assetFilename};`; 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /config/modules.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const paths = require('./paths'); 6 | const chalk = require('react-dev-utils/chalk'); 7 | const resolve = require('resolve'); 8 | 9 | /** 10 | * Get additional module paths based on the baseUrl of a compilerOptions object. 11 | * 12 | * @param {Object} options 13 | */ 14 | function getAdditionalModulePaths(options = {}) { 15 | const baseUrl = options.baseUrl; 16 | 17 | if (!baseUrl) { 18 | return ''; 19 | } 20 | 21 | const baseUrlResolved = path.resolve(paths.appPath, baseUrl); 22 | 23 | // We don't need to do anything if `baseUrl` is set to `node_modules`. This is 24 | // the default behavior. 25 | if (path.relative(paths.appNodeModules, baseUrlResolved) === '') { 26 | return null; 27 | } 28 | 29 | // Allow the user set the `baseUrl` to `appSrc`. 30 | if (path.relative(paths.appSrc, baseUrlResolved) === '') { 31 | return [paths.appSrc]; 32 | } 33 | 34 | // If the path is equal to the root directory we ignore it here. 35 | // We don't want to allow importing from the root directly as source files are 36 | // not transpiled outside of `src`. We do allow importing them with the 37 | // absolute path (e.g. `src/Components/Button.js`) but we set that up with 38 | // an alias. 39 | if (path.relative(paths.appPath, baseUrlResolved) === '') { 40 | return null; 41 | } 42 | 43 | // Otherwise, throw an error. 44 | throw new Error( 45 | chalk.red.bold( 46 | "Your project's `baseUrl` can only be set to `src` or `node_modules`." + 47 | ' Create React App does not support other values at this time.' 48 | ) 49 | ); 50 | } 51 | 52 | /** 53 | * Get webpack aliases based on the baseUrl of a compilerOptions object. 54 | * 55 | * @param {*} options 56 | */ 57 | function getWebpackAliases(options = {}) { 58 | const baseUrl = options.baseUrl; 59 | 60 | if (!baseUrl) { 61 | return {}; 62 | } 63 | 64 | const baseUrlResolved = path.resolve(paths.appPath, baseUrl); 65 | 66 | if (path.relative(paths.appPath, baseUrlResolved) === '') { 67 | return { 68 | src: paths.appSrc, 69 | }; 70 | } 71 | } 72 | 73 | /** 74 | * Get jest aliases based on the baseUrl of a compilerOptions object. 75 | * 76 | * @param {*} options 77 | */ 78 | function getJestAliases(options = {}) { 79 | const baseUrl = options.baseUrl; 80 | 81 | if (!baseUrl) { 82 | return {}; 83 | } 84 | 85 | const baseUrlResolved = path.resolve(paths.appPath, baseUrl); 86 | 87 | if (path.relative(paths.appPath, baseUrlResolved) === '') { 88 | return { 89 | '^src/(.*)$': '/src/$1', 90 | }; 91 | } 92 | } 93 | 94 | function getModules() { 95 | // Check if TypeScript is setup 96 | const hasTsConfig = fs.existsSync(paths.appTsConfig); 97 | const hasJsConfig = fs.existsSync(paths.appJsConfig); 98 | 99 | if (hasTsConfig && hasJsConfig) { 100 | throw new Error( 101 | 'You have both a tsconfig.json and a jsconfig.json. If you are using TypeScript please remove your jsconfig.json file.' 102 | ); 103 | } 104 | 105 | let config; 106 | 107 | // If there's a tsconfig.json we assume it's a 108 | // TypeScript project and set up the config 109 | // based on tsconfig.json 110 | if (hasTsConfig) { 111 | const ts = require(resolve.sync('typescript', { 112 | basedir: paths.appNodeModules, 113 | })); 114 | config = ts.readConfigFile(paths.appTsConfig, ts.sys.readFile).config; 115 | // Otherwise we'll check if there is jsconfig.json 116 | // for non TS projects. 117 | } else if (hasJsConfig) { 118 | config = require(paths.appJsConfig); 119 | } 120 | 121 | config = config || {}; 122 | const options = config.compilerOptions || {}; 123 | 124 | const additionalModulePaths = getAdditionalModulePaths(options); 125 | 126 | return { 127 | additionalModulePaths: additionalModulePaths, 128 | webpackAliases: getWebpackAliases(options), 129 | jestAliases: getJestAliases(options), 130 | hasTsConfig, 131 | }; 132 | } 133 | 134 | module.exports = getModules(); 135 | -------------------------------------------------------------------------------- /config/paths.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const fs = require('fs'); 5 | const getPublicUrlOrPath = require('react-dev-utils/getPublicUrlOrPath'); 6 | 7 | // Make sure any symlinks in the project folder are resolved: 8 | // https://github.com/facebook/create-react-app/issues/637 9 | const appDirectory = fs.realpathSync(process.cwd()); 10 | const resolveApp = relativePath => path.resolve(appDirectory, relativePath); 11 | 12 | // We use `PUBLIC_URL` environment variable or "homepage" field to infer 13 | // "public path" at which the app is served. 14 | // webpack needs to know it to put the right 9 | -------------------------------------------------------------------------------- /public/third-party/katex.min.css: -------------------------------------------------------------------------------- 1 | @font-face{font-family:KaTeX_AMS;src:url(fonts/KaTeX_AMS-Regular.eot);src:url(fonts/KaTeX_AMS-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_AMS-Regular.woff2) format('woff2'),url(fonts/KaTeX_AMS-Regular.woff) format('woff'),url(fonts/KaTeX_AMS-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Caligraphic;src:url(fonts/KaTeX_Caligraphic-Bold.eot);src:url(fonts/KaTeX_Caligraphic-Bold.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Caligraphic-Bold.woff2) format('woff2'),url(fonts/KaTeX_Caligraphic-Bold.woff) format('woff'),url(fonts/KaTeX_Caligraphic-Bold.ttf) format('truetype');font-weight:700;font-style:normal}@font-face{font-family:KaTeX_Caligraphic;src:url(fonts/KaTeX_Caligraphic-Regular.eot);src:url(fonts/KaTeX_Caligraphic-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Caligraphic-Regular.woff2) format('woff2'),url(fonts/KaTeX_Caligraphic-Regular.woff) format('woff'),url(fonts/KaTeX_Caligraphic-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Fraktur;src:url(fonts/KaTeX_Fraktur-Bold.eot);src:url(fonts/KaTeX_Fraktur-Bold.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Fraktur-Bold.woff2) format('woff2'),url(fonts/KaTeX_Fraktur-Bold.woff) format('woff'),url(fonts/KaTeX_Fraktur-Bold.ttf) format('truetype');font-weight:700;font-style:normal}@font-face{font-family:KaTeX_Fraktur;src:url(fonts/KaTeX_Fraktur-Regular.eot);src:url(fonts/KaTeX_Fraktur-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Fraktur-Regular.woff2) format('woff2'),url(fonts/KaTeX_Fraktur-Regular.woff) format('woff'),url(fonts/KaTeX_Fraktur-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Main;src:url(fonts/KaTeX_Main-Bold.eot);src:url(fonts/KaTeX_Main-Bold.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Main-Bold.woff2) format('woff2'),url(fonts/KaTeX_Main-Bold.woff) format('woff'),url(fonts/KaTeX_Main-Bold.ttf) format('truetype');font-weight:700;font-style:normal}@font-face{font-family:KaTeX_Main;src:url(fonts/KaTeX_Main-Italic.eot);src:url(fonts/KaTeX_Main-Italic.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Main-Italic.woff2) format('woff2'),url(fonts/KaTeX_Main-Italic.woff) format('woff'),url(fonts/KaTeX_Main-Italic.ttf) format('truetype');font-weight:400;font-style:italic}@font-face{font-family:KaTeX_Main;src:url(fonts/KaTeX_Main-Regular.eot);src:url(fonts/KaTeX_Main-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Main-Regular.woff2) format('woff2'),url(fonts/KaTeX_Main-Regular.woff) format('woff'),url(fonts/KaTeX_Main-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Math;src:url(fonts/KaTeX_Math-Italic.eot);src:url(fonts/KaTeX_Math-Italic.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Math-Italic.woff2) format('woff2'),url(fonts/KaTeX_Math-Italic.woff) format('woff'),url(fonts/KaTeX_Math-Italic.ttf) format('truetype');font-weight:400;font-style:italic}@font-face{font-family:KaTeX_SansSerif;src:url(fonts/KaTeX_SansSerif-Regular.eot);src:url(fonts/KaTeX_SansSerif-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_SansSerif-Regular.woff2) format('woff2'),url(fonts/KaTeX_SansSerif-Regular.woff) format('woff'),url(fonts/KaTeX_SansSerif-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Script;src:url(fonts/KaTeX_Script-Regular.eot);src:url(fonts/KaTeX_Script-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Script-Regular.woff2) format('woff2'),url(fonts/KaTeX_Script-Regular.woff) format('woff'),url(fonts/KaTeX_Script-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Size1;src:url(fonts/KaTeX_Size1-Regular.eot);src:url(fonts/KaTeX_Size1-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Size1-Regular.woff2) format('woff2'),url(fonts/KaTeX_Size1-Regular.woff) format('woff'),url(fonts/KaTeX_Size1-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Size2;src:url(fonts/KaTeX_Size2-Regular.eot);src:url(fonts/KaTeX_Size2-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Size2-Regular.woff2) format('woff2'),url(fonts/KaTeX_Size2-Regular.woff) format('woff'),url(fonts/KaTeX_Size2-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Size3;src:url(fonts/KaTeX_Size3-Regular.eot);src:url(fonts/KaTeX_Size3-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Size3-Regular.woff2) format('woff2'),url(fonts/KaTeX_Size3-Regular.woff) format('woff'),url(fonts/KaTeX_Size3-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Size4;src:url(fonts/KaTeX_Size4-Regular.eot);src:url(fonts/KaTeX_Size4-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Size4-Regular.woff2) format('woff2'),url(fonts/KaTeX_Size4-Regular.woff) format('woff'),url(fonts/KaTeX_Size4-Regular.ttf) format('truetype');font-weight:400;font-style:normal}@font-face{font-family:KaTeX_Typewriter;src:url(fonts/KaTeX_Typewriter-Regular.eot);src:url(fonts/KaTeX_Typewriter-Regular.eot#iefix) format('embedded-opentype'),url(fonts/KaTeX_Typewriter-Regular.woff2) format('woff2'),url(fonts/KaTeX_Typewriter-Regular.woff) format('woff'),url(fonts/KaTeX_Typewriter-Regular.ttf) format('truetype');font-weight:400;font-style:normal}.katex-display{display:block;margin:1em 0;text-align:center}.katex .base,.katex .katex-html,.katex .strut{display:inline-block}.katex-display>.katex{display:inline-block;text-align:initial}.katex{font:400 1.21em KaTeX_Main,Times New Roman,serif;line-height:1.2;white-space:nowrap;text-indent:0;text-rendering:auto}.katex *{-ms-high-contrast-adjust:none!important}.katex .katex-mathml{position:absolute;clip:rect(1px,1px,1px,1px);padding:0;border:0;height:1px;width:1px;overflow:hidden}.katex .base{position:relative}.katex .mathrm{font-style:normal}.katex .mainit,.katex .mathit,.katex .textit{font-style:italic}.katex .mathit{font-family:KaTeX_Math}.katex .mathbf{font-family:KaTeX_Main;font-weight:700}.katex .amsrm,.katex .mathbb{font-family:KaTeX_AMS}.katex .mathcal{font-family:KaTeX_Caligraphic}.katex .mathfrak{font-family:KaTeX_Fraktur}.katex .mathtt{font-family:KaTeX_Typewriter}.katex .mathscr{font-family:KaTeX_Script}.katex .mathsf{font-family:KaTeX_SansSerif}.katex .mainit{font-family:KaTeX_Main}.katex .mainrm{font-family:KaTeX_Main;font-style:normal}.katex .mord+.mop{margin-left:.16667em}.katex .mord+.mbin{margin-left:.22222em}.katex .mord+.mrel{margin-left:.27778em}.katex .mop+.mop,.katex .mop+.mord,.katex .mord+.minner{margin-left:.16667em}.katex .mop+.mrel{margin-left:.27778em}.katex .mop+.minner{margin-left:.16667em}.katex .mbin+.minner,.katex .mbin+.mop,.katex .mbin+.mopen,.katex .mbin+.mord{margin-left:.22222em}.katex .mrel+.minner,.katex .mrel+.mop,.katex .mrel+.mopen,.katex .mrel+.mord{margin-left:.27778em}.katex .mclose+.mop{margin-left:.16667em}.katex .mclose+.mbin{margin-left:.22222em}.katex .mclose+.mrel{margin-left:.27778em}.katex .mclose+.minner,.katex .minner+.mop,.katex .minner+.mord,.katex .mpunct+.mclose,.katex .mpunct+.minner,.katex .mpunct+.mop,.katex .mpunct+.mopen,.katex .mpunct+.mord,.katex .mpunct+.mpunct,.katex .mpunct+.mrel{margin-left:.16667em}.katex .minner+.mbin{margin-left:.22222em}.katex .minner+.mrel{margin-left:.27778em}.katex .minner+.minner,.katex .minner+.mopen,.katex .minner+.mpunct{margin-left:.16667em}.katex .mbin.mtight,.katex .mclose.mtight,.katex .minner.mtight,.katex .mop.mtight,.katex .mopen.mtight,.katex .mord.mtight,.katex .mpunct.mtight,.katex .mrel.mtight{margin-left:0}.katex .mclose+.mop.mtight,.katex .minner+.mop.mtight,.katex .mop+.mop.mtight,.katex .mop+.mord.mtight,.katex .mord+.mop.mtight{margin-left:.16667em}.katex .vlist-t{display:inline-table;table-layout:fixed}.katex .vlist-r{display:table-row}.katex .vlist{display:table-cell;vertical-align:bottom;position:relative}.katex .vlist>span{display:block;height:0;position:relative}.katex .vlist>span>span{display:inline-block}.katex .vlist>span>.pstrut{overflow:hidden;width:0}.katex .vlist-t2{margin-right:-2px}.katex .vlist-s{display:table-cell;vertical-align:bottom;font-size:1px;width:2px}.katex .fontsize-ensurer,.katex .llap>.fix,.katex .mfrac .frac-line,.katex .mspace,.katex .mtable .arraycolsep,.katex .mtable .vertical-separator,.katex .nulldelimiter,.katex .rlap>.fix,.katex .rule,.katex .sizing{display:inline-block}.katex .msupsub{text-align:left}.katex .accent>.vlist-t,.katex .mfrac>span>span,.katex .mtable .col-align-c>.vlist-t,.katex .op-limits>.vlist-t{text-align:center}.katex .mfrac .frac-line{width:100%;border-bottom-style:solid}.katex .mspace.negativethinspace{margin-left:-.16667em}.katex .mspace.thinspace{width:.16667em}.katex .mspace.negativemediumspace{margin-left:-.22222em}.katex .mspace.mediumspace{width:.22222em}.katex .mspace.thickspace{width:.27778em}.katex .mspace.sixmuspace{width:.333333em}.katex .mspace.eightmuspace{width:.444444em}.katex .mspace.enspace{width:.5em}.katex .mspace.twelvemuspace{width:.666667em}.katex .mspace.quad{width:1em}.katex .mspace.qquad{width:2em}.katex .llap,.katex .rlap{width:0;position:relative}.katex .llap>.inner,.katex .rlap>.inner{position:absolute}.katex .llap>.inner{right:0}.katex .rlap>.inner{left:0}.katex .katex-logo .a{font-size:.75em;margin-left:-.32em;position:relative;top:-.2em}.katex .katex-logo .t{margin-left:-.23em}.katex .katex-logo .e{margin-left:-.1667em;position:relative;top:.2155em}.katex .katex-logo .x{margin-left:-.125em}.katex .rule{border:0 solid;position:relative}.katex .overline .overline-line,.katex .underline .underline-line{display:inline-block;width:100%;border-bottom-style:solid}.katex .sqrt>.root{margin-left:.27777778em;margin-right:-.55555556em}.katex .fontsize-ensurer.reset-size1.size1,.katex .sizing.reset-size1.size1{font-size:1em}.katex .fontsize-ensurer.reset-size1.size2,.katex .sizing.reset-size1.size2{font-size:1.2em}.katex .fontsize-ensurer.reset-size1.size3,.katex .sizing.reset-size1.size3{font-size:1.4em}.katex .fontsize-ensurer.reset-size1.size4,.katex .sizing.reset-size1.size4{font-size:1.6em}.katex .fontsize-ensurer.reset-size1.size5,.katex .sizing.reset-size1.size5{font-size:1.8em}.katex .fontsize-ensurer.reset-size1.size6,.katex .sizing.reset-size1.size6{font-size:2em}.katex .fontsize-ensurer.reset-size1.size7,.katex .sizing.reset-size1.size7{font-size:2.4em}.katex .fontsize-ensurer.reset-size1.size8,.katex .sizing.reset-size1.size8{font-size:2.88em}.katex .fontsize-ensurer.reset-size1.size9,.katex .sizing.reset-size1.size9{font-size:3.456em}.katex .fontsize-ensurer.reset-size1.size10,.katex .sizing.reset-size1.size10{font-size:4.148em}.katex .fontsize-ensurer.reset-size1.size11,.katex .sizing.reset-size1.size11{font-size:4.976em}.katex .fontsize-ensurer.reset-size2.size1,.katex .sizing.reset-size2.size1{font-size:.83333333em}.katex .fontsize-ensurer.reset-size2.size2,.katex .sizing.reset-size2.size2{font-size:1em}.katex .fontsize-ensurer.reset-size2.size3,.katex .sizing.reset-size2.size3{font-size:1.16666667em}.katex .fontsize-ensurer.reset-size2.size4,.katex .sizing.reset-size2.size4{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size2.size5,.katex .sizing.reset-size2.size5{font-size:1.5em}.katex .fontsize-ensurer.reset-size2.size6,.katex .sizing.reset-size2.size6{font-size:1.66666667em}.katex .fontsize-ensurer.reset-size2.size7,.katex .sizing.reset-size2.size7{font-size:2em}.katex .fontsize-ensurer.reset-size2.size8,.katex .sizing.reset-size2.size8{font-size:2.4em}.katex .fontsize-ensurer.reset-size2.size9,.katex .sizing.reset-size2.size9{font-size:2.88em}.katex .fontsize-ensurer.reset-size2.size10,.katex .sizing.reset-size2.size10{font-size:3.45666667em}.katex .fontsize-ensurer.reset-size2.size11,.katex .sizing.reset-size2.size11{font-size:4.14666667em}.katex .fontsize-ensurer.reset-size3.size1,.katex .sizing.reset-size3.size1{font-size:.71428571em}.katex .fontsize-ensurer.reset-size3.size2,.katex .sizing.reset-size3.size2{font-size:.85714286em}.katex .fontsize-ensurer.reset-size3.size3,.katex .sizing.reset-size3.size3{font-size:1em}.katex .fontsize-ensurer.reset-size3.size4,.katex .sizing.reset-size3.size4{font-size:1.14285714em}.katex .fontsize-ensurer.reset-size3.size5,.katex .sizing.reset-size3.size5{font-size:1.28571429em}.katex .fontsize-ensurer.reset-size3.size6,.katex .sizing.reset-size3.size6{font-size:1.42857143em}.katex .fontsize-ensurer.reset-size3.size7,.katex .sizing.reset-size3.size7{font-size:1.71428571em}.katex .fontsize-ensurer.reset-size3.size8,.katex .sizing.reset-size3.size8{font-size:2.05714286em}.katex .fontsize-ensurer.reset-size3.size9,.katex .sizing.reset-size3.size9{font-size:2.46857143em}.katex .fontsize-ensurer.reset-size3.size10,.katex .sizing.reset-size3.size10{font-size:2.96285714em}.katex .fontsize-ensurer.reset-size3.size11,.katex .sizing.reset-size3.size11{font-size:3.55428571em}.katex .fontsize-ensurer.reset-size4.size1,.katex .sizing.reset-size4.size1{font-size:.625em}.katex .fontsize-ensurer.reset-size4.size2,.katex .sizing.reset-size4.size2{font-size:.75em}.katex .fontsize-ensurer.reset-size4.size3,.katex .sizing.reset-size4.size3{font-size:.875em}.katex .fontsize-ensurer.reset-size4.size4,.katex .sizing.reset-size4.size4{font-size:1em}.katex .fontsize-ensurer.reset-size4.size5,.katex .sizing.reset-size4.size5{font-size:1.125em}.katex .fontsize-ensurer.reset-size4.size6,.katex .sizing.reset-size4.size6{font-size:1.25em}.katex .fontsize-ensurer.reset-size4.size7,.katex .sizing.reset-size4.size7{font-size:1.5em}.katex .fontsize-ensurer.reset-size4.size8,.katex .sizing.reset-size4.size8{font-size:1.8em}.katex .fontsize-ensurer.reset-size4.size9,.katex .sizing.reset-size4.size9{font-size:2.16em}.katex .fontsize-ensurer.reset-size4.size10,.katex .sizing.reset-size4.size10{font-size:2.5925em}.katex .fontsize-ensurer.reset-size4.size11,.katex .sizing.reset-size4.size11{font-size:3.11em}.katex .fontsize-ensurer.reset-size5.size1,.katex .sizing.reset-size5.size1{font-size:.55555556em}.katex .fontsize-ensurer.reset-size5.size2,.katex .sizing.reset-size5.size2{font-size:.66666667em}.katex .fontsize-ensurer.reset-size5.size3,.katex .sizing.reset-size5.size3{font-size:.77777778em}.katex .fontsize-ensurer.reset-size5.size4,.katex .sizing.reset-size5.size4{font-size:.88888889em}.katex .fontsize-ensurer.reset-size5.size5,.katex .sizing.reset-size5.size5{font-size:1em}.katex .fontsize-ensurer.reset-size5.size6,.katex .sizing.reset-size5.size6{font-size:1.11111111em}.katex .fontsize-ensurer.reset-size5.size7,.katex .sizing.reset-size5.size7{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size5.size8,.katex .sizing.reset-size5.size8{font-size:1.6em}.katex .fontsize-ensurer.reset-size5.size9,.katex .sizing.reset-size5.size9{font-size:1.92em}.katex .fontsize-ensurer.reset-size5.size10,.katex .sizing.reset-size5.size10{font-size:2.30444444em}.katex .fontsize-ensurer.reset-size5.size11,.katex .sizing.reset-size5.size11{font-size:2.76444444em}.katex .fontsize-ensurer.reset-size6.size1,.katex .sizing.reset-size6.size1{font-size:.5em}.katex .fontsize-ensurer.reset-size6.size2,.katex .sizing.reset-size6.size2{font-size:.6em}.katex .fontsize-ensurer.reset-size6.size3,.katex .sizing.reset-size6.size3{font-size:.7em}.katex .fontsize-ensurer.reset-size6.size4,.katex .sizing.reset-size6.size4{font-size:.8em}.katex .fontsize-ensurer.reset-size6.size5,.katex .sizing.reset-size6.size5{font-size:.9em}.katex .fontsize-ensurer.reset-size6.size6,.katex .sizing.reset-size6.size6{font-size:1em}.katex .fontsize-ensurer.reset-size6.size7,.katex .sizing.reset-size6.size7{font-size:1.2em}.katex .fontsize-ensurer.reset-size6.size8,.katex .sizing.reset-size6.size8{font-size:1.44em}.katex .fontsize-ensurer.reset-size6.size9,.katex .sizing.reset-size6.size9{font-size:1.728em}.katex .fontsize-ensurer.reset-size6.size10,.katex .sizing.reset-size6.size10{font-size:2.074em}.katex .fontsize-ensurer.reset-size6.size11,.katex .sizing.reset-size6.size11{font-size:2.488em}.katex .fontsize-ensurer.reset-size7.size1,.katex .sizing.reset-size7.size1{font-size:.41666667em}.katex .fontsize-ensurer.reset-size7.size2,.katex .sizing.reset-size7.size2{font-size:.5em}.katex .fontsize-ensurer.reset-size7.size3,.katex .sizing.reset-size7.size3{font-size:.58333333em}.katex .fontsize-ensurer.reset-size7.size4,.katex .sizing.reset-size7.size4{font-size:.66666667em}.katex .fontsize-ensurer.reset-size7.size5,.katex .sizing.reset-size7.size5{font-size:.75em}.katex .fontsize-ensurer.reset-size7.size6,.katex .sizing.reset-size7.size6{font-size:.83333333em}.katex .fontsize-ensurer.reset-size7.size7,.katex .sizing.reset-size7.size7{font-size:1em}.katex .fontsize-ensurer.reset-size7.size8,.katex .sizing.reset-size7.size8{font-size:1.2em}.katex .fontsize-ensurer.reset-size7.size9,.katex .sizing.reset-size7.size9{font-size:1.44em}.katex .fontsize-ensurer.reset-size7.size10,.katex .sizing.reset-size7.size10{font-size:1.72833333em}.katex .fontsize-ensurer.reset-size7.size11,.katex .sizing.reset-size7.size11{font-size:2.07333333em}.katex .fontsize-ensurer.reset-size8.size1,.katex .sizing.reset-size8.size1{font-size:.34722222em}.katex .fontsize-ensurer.reset-size8.size2,.katex .sizing.reset-size8.size2{font-size:.41666667em}.katex .fontsize-ensurer.reset-size8.size3,.katex .sizing.reset-size8.size3{font-size:.48611111em}.katex .fontsize-ensurer.reset-size8.size4,.katex .sizing.reset-size8.size4{font-size:.55555556em}.katex .fontsize-ensurer.reset-size8.size5,.katex .sizing.reset-size8.size5{font-size:.625em}.katex .fontsize-ensurer.reset-size8.size6,.katex .sizing.reset-size8.size6{font-size:.69444444em}.katex .fontsize-ensurer.reset-size8.size7,.katex .sizing.reset-size8.size7{font-size:.83333333em}.katex .fontsize-ensurer.reset-size8.size8,.katex .sizing.reset-size8.size8{font-size:1em}.katex .fontsize-ensurer.reset-size8.size9,.katex .sizing.reset-size8.size9{font-size:1.2em}.katex .fontsize-ensurer.reset-size8.size10,.katex .sizing.reset-size8.size10{font-size:1.44027778em}.katex .fontsize-ensurer.reset-size8.size11,.katex .sizing.reset-size8.size11{font-size:1.72777778em}.katex .fontsize-ensurer.reset-size9.size1,.katex .sizing.reset-size9.size1{font-size:.28935185em}.katex .fontsize-ensurer.reset-size9.size2,.katex .sizing.reset-size9.size2{font-size:.34722222em}.katex .fontsize-ensurer.reset-size9.size3,.katex .sizing.reset-size9.size3{font-size:.40509259em}.katex .fontsize-ensurer.reset-size9.size4,.katex .sizing.reset-size9.size4{font-size:.46296296em}.katex .fontsize-ensurer.reset-size9.size5,.katex .sizing.reset-size9.size5{font-size:.52083333em}.katex .fontsize-ensurer.reset-size9.size6,.katex .sizing.reset-size9.size6{font-size:.5787037em}.katex .fontsize-ensurer.reset-size9.size7,.katex .sizing.reset-size9.size7{font-size:.69444444em}.katex .fontsize-ensurer.reset-size9.size8,.katex .sizing.reset-size9.size8{font-size:.83333333em}.katex .fontsize-ensurer.reset-size9.size9,.katex .sizing.reset-size9.size9{font-size:1em}.katex .fontsize-ensurer.reset-size9.size10,.katex .sizing.reset-size9.size10{font-size:1.20023148em}.katex .fontsize-ensurer.reset-size9.size11,.katex .sizing.reset-size9.size11{font-size:1.43981481em}.katex .fontsize-ensurer.reset-size10.size1,.katex .sizing.reset-size10.size1{font-size:.24108004em}.katex .fontsize-ensurer.reset-size10.size2,.katex .sizing.reset-size10.size2{font-size:.28929605em}.katex .fontsize-ensurer.reset-size10.size3,.katex .sizing.reset-size10.size3{font-size:.33751205em}.katex .fontsize-ensurer.reset-size10.size4,.katex .sizing.reset-size10.size4{font-size:.38572806em}.katex .fontsize-ensurer.reset-size10.size5,.katex .sizing.reset-size10.size5{font-size:.43394407em}.katex .fontsize-ensurer.reset-size10.size6,.katex .sizing.reset-size10.size6{font-size:.48216008em}.katex .fontsize-ensurer.reset-size10.size7,.katex .sizing.reset-size10.size7{font-size:.57859209em}.katex .fontsize-ensurer.reset-size10.size8,.katex .sizing.reset-size10.size8{font-size:.69431051em}.katex .fontsize-ensurer.reset-size10.size9,.katex .sizing.reset-size10.size9{font-size:.83317261em}.katex .fontsize-ensurer.reset-size10.size10,.katex .sizing.reset-size10.size10{font-size:1em}.katex .fontsize-ensurer.reset-size10.size11,.katex .sizing.reset-size10.size11{font-size:1.19961427em}.katex .fontsize-ensurer.reset-size11.size1,.katex .sizing.reset-size11.size1{font-size:.20096463em}.katex .fontsize-ensurer.reset-size11.size2,.katex .sizing.reset-size11.size2{font-size:.24115756em}.katex .fontsize-ensurer.reset-size11.size3,.katex .sizing.reset-size11.size3{font-size:.28135048em}.katex .fontsize-ensurer.reset-size11.size4,.katex .sizing.reset-size11.size4{font-size:.32154341em}.katex .fontsize-ensurer.reset-size11.size5,.katex .sizing.reset-size11.size5{font-size:.36173633em}.katex .fontsize-ensurer.reset-size11.size6,.katex .sizing.reset-size11.size6{font-size:.40192926em}.katex .fontsize-ensurer.reset-size11.size7,.katex .sizing.reset-size11.size7{font-size:.48231511em}.katex .fontsize-ensurer.reset-size11.size8,.katex .sizing.reset-size11.size8{font-size:.57877814em}.katex .fontsize-ensurer.reset-size11.size9,.katex .sizing.reset-size11.size9{font-size:.69453376em}.katex .fontsize-ensurer.reset-size11.size10,.katex .sizing.reset-size11.size10{font-size:.83360129em}.katex .fontsize-ensurer.reset-size11.size11,.katex .sizing.reset-size11.size11{font-size:1em}.katex .delimsizing.size1{font-family:KaTeX_Size1}.katex .delimsizing.size2{font-family:KaTeX_Size2}.katex .delimsizing.size3{font-family:KaTeX_Size3}.katex .delimsizing.size4{font-family:KaTeX_Size4}.katex .delimsizing.mult .delim-size1>span{font-family:KaTeX_Size1}.katex .delimsizing.mult .delim-size4>span{font-family:KaTeX_Size4}.katex .nulldelimiter{width:.12em}.katex .delimcenter,.katex .op-symbol{position:relative}.katex .op-symbol.small-op{font-family:KaTeX_Size1}.katex .op-symbol.large-op{font-family:KaTeX_Size2}.katex .accent .accent-body>span{width:0}.katex .accent .accent-body.accent-vec>span{position:relative;left:.326em}.katex .accent .accent-body.accent-hungarian>span{position:relative;left:.25em}.katex .mtable .vertical-separator{margin:0 -.025em;border-right:.05em solid #000}.katex .stretchy,.katex svg{width:100%;display:block}.katex .mtable .col-align-l>.vlist-t{text-align:left}.katex .mtable .col-align-r>.vlist-t{text-align:right}.katex .svg-align{text-align:left}.katex svg{position:absolute}.katex svg path{fill:currentColor}.katex svg line{stroke:currentColor}.katex .stretchy:after,.katex .stretchy:before{content:""}.katex .x-arrow-pad{padding:0 .5em}.katex .mover,.katex .munder,.katex .x-arrow{text-align:center}.katex .boxpad{padding:0 .3em}.katex .fbox{box-sizing:border-box;border:.04em solid #000}.katex .cancel-pad{padding:0 .2em}.katex .cancel-lap+.mbin,.katex .cancel-lap+.mord,.katex .cancel-lap+.msupsub,.katex .mbin+.cancel-lap,.katex .mord+.cancel-lap{margin-left:-.2em}.katex .sout{border-bottom-style:solid;border-bottom-width:.08em} -------------------------------------------------------------------------------- /scripts/build.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Do this as the first thing so that any code reading it knows the right env. 4 | process.env.BABEL_ENV = 'production'; 5 | process.env.NODE_ENV = 'production'; 6 | 7 | // Makes the script crash on unhandled rejections instead of silently 8 | // ignoring them. In the future, promise rejections that are not handled will 9 | // terminate the Node.js process with a non-zero exit code. 10 | process.on('unhandledRejection', err => { 11 | throw err; 12 | }); 13 | 14 | // Ensure environment variables are read. 15 | require('../config/env'); 16 | 17 | const path = require('path'); 18 | const chalk = require('react-dev-utils/chalk'); 19 | const fs = require('fs-extra'); 20 | const bfj = require('bfj'); 21 | const webpack = require('webpack'); 22 | const configFactory = require('../config/webpack.config'); 23 | const paths = require('../config/paths'); 24 | const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles'); 25 | const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages'); 26 | const printHostingInstructions = require('react-dev-utils/printHostingInstructions'); 27 | const FileSizeReporter = require('react-dev-utils/FileSizeReporter'); 28 | const printBuildError = require('react-dev-utils/printBuildError'); 29 | 30 | const measureFileSizesBeforeBuild = 31 | FileSizeReporter.measureFileSizesBeforeBuild; 32 | const printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild; 33 | const useYarn = fs.existsSync(paths.yarnLockFile); 34 | 35 | // These sizes are pretty large. We'll warn for bundles exceeding them. 36 | const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024; 37 | const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024; 38 | 39 | const isInteractive = process.stdout.isTTY; 40 | 41 | // Warn and crash if required files are missing 42 | if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) { 43 | process.exit(1); 44 | } 45 | 46 | const argv = process.argv.slice(2); 47 | const writeStatsJson = argv.indexOf('--stats') !== -1; 48 | 49 | // Generate configuration 50 | const config = configFactory('production'); 51 | 52 | // We require that you explicitly set browsers and do not fall back to 53 | // browserslist defaults. 54 | const { checkBrowsers } = require('react-dev-utils/browsersHelper'); 55 | checkBrowsers(paths.appPath, isInteractive) 56 | .then(() => { 57 | // First, read the current file sizes in build directory. 58 | // This lets us display how much they changed later. 59 | return measureFileSizesBeforeBuild(paths.appBuild); 60 | }) 61 | .then(previousFileSizes => { 62 | // Remove all content but keep the directory so that 63 | // if you're in it, you don't end up in Trash 64 | fs.emptyDirSync(paths.appBuild); 65 | // Merge with the public folder 66 | copyPublicFolder(); 67 | // Start the webpack build 68 | return build(previousFileSizes); 69 | }) 70 | .then( 71 | ({ stats, previousFileSizes, warnings }) => { 72 | if (warnings.length) { 73 | console.log(chalk.yellow('Compiled with warnings.\n')); 74 | console.log(warnings.join('\n\n')); 75 | console.log( 76 | '\nSearch for the ' + 77 | chalk.underline(chalk.yellow('keywords')) + 78 | ' to learn more about each warning.' 79 | ); 80 | console.log( 81 | 'To ignore, add ' + 82 | chalk.cyan('// eslint-disable-next-line') + 83 | ' to the line before.\n' 84 | ); 85 | } else { 86 | console.log(chalk.green('Compiled successfully.\n')); 87 | } 88 | 89 | console.log('File sizes after gzip:\n'); 90 | printFileSizesAfterBuild( 91 | stats, 92 | previousFileSizes, 93 | paths.appBuild, 94 | WARN_AFTER_BUNDLE_GZIP_SIZE, 95 | WARN_AFTER_CHUNK_GZIP_SIZE 96 | ); 97 | console.log(); 98 | 99 | const appPackage = require(paths.appPackageJson); 100 | const publicUrl = paths.publicUrlOrPath; 101 | const publicPath = config.output.publicPath; 102 | const buildFolder = path.relative(process.cwd(), paths.appBuild); 103 | printHostingInstructions( 104 | appPackage, 105 | publicUrl, 106 | publicPath, 107 | buildFolder, 108 | useYarn 109 | ); 110 | }, 111 | err => { 112 | const tscCompileOnError = process.env.TSC_COMPILE_ON_ERROR === 'true'; 113 | if (tscCompileOnError) { 114 | console.log( 115 | chalk.yellow( 116 | 'Compiled with the following type errors (you may want to check these before deploying your app):\n' 117 | ) 118 | ); 119 | printBuildError(err); 120 | } else { 121 | console.log(chalk.red('Failed to compile.\n')); 122 | printBuildError(err); 123 | process.exit(1); 124 | } 125 | } 126 | ) 127 | .catch(err => { 128 | if (err && err.message) { 129 | console.log(err.message); 130 | } 131 | process.exit(1); 132 | }); 133 | 134 | // Create the production build and print the deployment instructions. 135 | function build(previousFileSizes) { 136 | console.log('Creating an optimized production build...'); 137 | 138 | const compiler = webpack(config); 139 | return new Promise((resolve, reject) => { 140 | compiler.run((err, stats) => { 141 | let messages; 142 | if (err) { 143 | if (!err.message) { 144 | return reject(err); 145 | } 146 | 147 | let errMessage = err.message; 148 | 149 | // Add additional information for postcss errors 150 | if (Object.prototype.hasOwnProperty.call(err, 'postcssNode')) { 151 | errMessage += 152 | '\nCompileError: Begins at CSS selector ' + 153 | err['postcssNode'].selector; 154 | } 155 | 156 | messages = formatWebpackMessages({ 157 | errors: [errMessage], 158 | warnings: [], 159 | }); 160 | } else { 161 | messages = formatWebpackMessages( 162 | stats.toJson({ all: false, warnings: true, errors: true }) 163 | ); 164 | } 165 | if (messages.errors.length) { 166 | // Only keep the first error. Others are often indicative 167 | // of the same problem, but confuse the reader with noise. 168 | if (messages.errors.length > 1) { 169 | messages.errors.length = 1; 170 | } 171 | return reject(new Error(messages.errors.join('\n\n'))); 172 | } 173 | if ( 174 | process.env.CI && 175 | (typeof process.env.CI !== 'string' || 176 | process.env.CI.toLowerCase() !== 'false') && 177 | messages.warnings.length 178 | ) { 179 | // Ignore sourcemap warnings in CI builds. See #8227 for more info. 180 | const filteredWarnings = messages.warnings.filter( 181 | w => !/Failed to parse source map/.test(w) 182 | ); 183 | if (filteredWarnings.length) { 184 | console.log( 185 | chalk.yellow( 186 | '\nTreating warnings as errors because process.env.CI = true.\n' + 187 | 'Most CI servers set it automatically.\n' 188 | ) 189 | ); 190 | return reject(new Error(filteredWarnings.join('\n\n'))); 191 | } 192 | } 193 | 194 | const resolveArgs = { 195 | stats, 196 | previousFileSizes, 197 | warnings: messages.warnings, 198 | }; 199 | 200 | if (writeStatsJson) { 201 | return bfj 202 | .write(paths.appBuild + '/bundle-stats.json', stats.toJson()) 203 | .then(() => resolve(resolveArgs)) 204 | .catch(error => reject(new Error(error))); 205 | } 206 | 207 | return resolve(resolveArgs); 208 | }); 209 | }); 210 | } 211 | 212 | function copyPublicFolder() { 213 | fs.copySync(paths.appPublic, paths.appBuild, { 214 | dereference: true, 215 | filter: file => file !== paths.appHtml, 216 | }); 217 | } 218 | -------------------------------------------------------------------------------- /scripts/start.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Do this as the first thing so that any code reading it knows the right env. 4 | process.env.BABEL_ENV = 'development'; 5 | process.env.NODE_ENV = 'development'; 6 | 7 | // Makes the script crash on unhandled rejections instead of silently 8 | // ignoring them. In the future, promise rejections that are not handled will 9 | // terminate the Node.js process with a non-zero exit code. 10 | process.on('unhandledRejection', err => { 11 | throw err; 12 | }); 13 | 14 | // Ensure environment variables are read. 15 | require('../config/env'); 16 | 17 | const fs = require('fs'); 18 | const chalk = require('react-dev-utils/chalk'); 19 | const webpack = require('webpack'); 20 | const WebpackDevServer = require('webpack-dev-server'); 21 | const clearConsole = require('react-dev-utils/clearConsole'); 22 | const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles'); 23 | const { 24 | choosePort, 25 | createCompiler, 26 | prepareProxy, 27 | prepareUrls, 28 | } = require('react-dev-utils/WebpackDevServerUtils'); 29 | const openBrowser = require('react-dev-utils/openBrowser'); 30 | const semver = require('semver'); 31 | const paths = require('../config/paths'); 32 | const configFactory = require('../config/webpack.config'); 33 | const createDevServerConfig = require('../config/webpackDevServer.config'); 34 | const getClientEnvironment = require('../config/env'); 35 | const react = require(require.resolve('react', { paths: [paths.appPath] })); 36 | 37 | const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1)); 38 | const useYarn = fs.existsSync(paths.yarnLockFile); 39 | const isInteractive = process.stdout.isTTY; 40 | 41 | // Warn and crash if required files are missing 42 | if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) { 43 | process.exit(1); 44 | } 45 | 46 | // Tools like Cloud9 rely on this. 47 | const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000; 48 | const HOST = process.env.HOST || '0.0.0.0'; 49 | 50 | if (process.env.HOST) { 51 | console.log( 52 | chalk.cyan( 53 | `Attempting to bind to HOST environment variable: ${chalk.yellow( 54 | chalk.bold(process.env.HOST) 55 | )}` 56 | ) 57 | ); 58 | console.log( 59 | `If this was unintentional, check that you haven't mistakenly set it in your shell.` 60 | ); 61 | console.log( 62 | `Learn more here: ${chalk.yellow('https://cra.link/advanced-config')}` 63 | ); 64 | console.log(); 65 | } 66 | 67 | // We require that you explicitly set browsers and do not fall back to 68 | // browserslist defaults. 69 | const { checkBrowsers } = require('react-dev-utils/browsersHelper'); 70 | checkBrowsers(paths.appPath, isInteractive) 71 | .then(() => { 72 | // We attempt to use the default port but if it is busy, we offer the user to 73 | // run on a different port. `choosePort()` Promise resolves to the next free port. 74 | return choosePort(HOST, DEFAULT_PORT); 75 | }) 76 | .then(port => { 77 | if (port == null) { 78 | // We have not found a port. 79 | return; 80 | } 81 | 82 | const config = configFactory('development'); 83 | const protocol = process.env.HTTPS === 'true' ? 'https' : 'http'; 84 | const appName = require(paths.appPackageJson).name; 85 | 86 | const useTypeScript = fs.existsSync(paths.appTsConfig); 87 | const urls = prepareUrls( 88 | protocol, 89 | HOST, 90 | port, 91 | paths.publicUrlOrPath.slice(0, -1) 92 | ); 93 | // Create a webpack compiler that is configured with custom messages. 94 | const compiler = createCompiler({ 95 | appName, 96 | config, 97 | urls, 98 | useYarn, 99 | useTypeScript, 100 | webpack, 101 | }); 102 | // Load proxy config 103 | const proxySetting = require(paths.appPackageJson).proxy; 104 | const proxyConfig = prepareProxy( 105 | proxySetting, 106 | paths.appPublic, 107 | paths.publicUrlOrPath 108 | ); 109 | // Serve webpack assets generated by the compiler over a web server. 110 | const serverConfig = { 111 | ...createDevServerConfig(proxyConfig, urls.lanUrlForConfig), 112 | host: HOST, 113 | port, 114 | }; 115 | const devServer = new WebpackDevServer(serverConfig, compiler); 116 | // Launch WebpackDevServer. 117 | devServer.startCallback(() => { 118 | if (isInteractive) { 119 | clearConsole(); 120 | } 121 | 122 | if (env.raw.FAST_REFRESH && semver.lt(react.version, '16.10.0')) { 123 | console.log( 124 | chalk.yellow( 125 | `Fast Refresh requires React 16.10 or higher. You are using React ${react.version}.` 126 | ) 127 | ); 128 | } 129 | 130 | console.log(chalk.cyan('Starting the development server...\n')); 131 | openBrowser(urls.localUrlForBrowser); 132 | }); 133 | 134 | ['SIGINT', 'SIGTERM'].forEach(function (sig) { 135 | process.on(sig, function () { 136 | devServer.close(); 137 | process.exit(); 138 | }); 139 | }); 140 | 141 | if (process.env.CI !== 'true') { 142 | // Gracefully exit when stdin ends 143 | process.stdin.on('end', function () { 144 | devServer.close(); 145 | process.exit(); 146 | }); 147 | } 148 | }) 149 | .catch(err => { 150 | if (err && err.message) { 151 | console.log(err.message); 152 | } 153 | process.exit(1); 154 | }); 155 | -------------------------------------------------------------------------------- /scripts/test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Do this as the first thing so that any code reading it knows the right env. 4 | process.env.BABEL_ENV = 'test'; 5 | process.env.NODE_ENV = 'test'; 6 | process.env.PUBLIC_URL = ''; 7 | 8 | // Makes the script crash on unhandled rejections instead of silently 9 | // ignoring them. In the future, promise rejections that are not handled will 10 | // terminate the Node.js process with a non-zero exit code. 11 | process.on('unhandledRejection', err => { 12 | throw err; 13 | }); 14 | 15 | // Ensure environment variables are read. 16 | require('../config/env'); 17 | 18 | const jest = require('jest'); 19 | const execSync = require('child_process').execSync; 20 | let argv = process.argv.slice(2); 21 | 22 | function isInGitRepository() { 23 | try { 24 | execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' }); 25 | return true; 26 | } catch (e) { 27 | return false; 28 | } 29 | } 30 | 31 | function isInMercurialRepository() { 32 | try { 33 | execSync('hg --cwd . root', { stdio: 'ignore' }); 34 | return true; 35 | } catch (e) { 36 | return false; 37 | } 38 | } 39 | 40 | // Watch unless on CI or explicitly running all tests 41 | if ( 42 | !process.env.CI && 43 | argv.indexOf('--watchAll') === -1 && 44 | argv.indexOf('--watchAll=false') === -1 45 | ) { 46 | // https://github.com/facebook/create-react-app/issues/5210 47 | const hasSourceControl = isInGitRepository() || isInMercurialRepository(); 48 | argv.push(hasSourceControl ? '--watch' : '--watchAll'); 49 | } 50 | 51 | 52 | jest.run(argv); 53 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import logo from './logo.svg'; 2 | import './App.css'; 3 | 4 | function App() { 5 | return ( 6 |
7 |
8 | logo 9 |

10 | Edit src/App.js and save to reload. 11 |

12 | 18 | Learn React 19 | 20 |
21 |
22 | ); 23 | } 24 | 25 | export default App; 26 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /src/components/hidden.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export default ({ children }) => { 4 | // return ( 5 | // 6 | // 7 | // ); 8 | return ; 9 | }; 10 | -------------------------------------------------------------------------------- /src/components/tokenheatmap.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const DEFAULT_COLORS = [ 4 | // { r: 255, g: 0, b: 105 }, 5 | { r: 255, g: 255, b: 255 }, 6 | { r: 0, g: 255, b: 0 }, 7 | ] 8 | const DEFAULT_BOUNDARIES = [ 9 | // 0, 0.5, 1 10 | 0, 1 11 | ] 12 | 13 | function interpolateColor(color_l, color_r, value) { 14 | const color = { 15 | r: Math.round(color_l.r + (color_r.r - color_l.r) * value), 16 | g: Math.round(color_l.g + (color_r.g - color_l.g) * value), 17 | b: Math.round(color_l.b + (color_r.b - color_l.b) * value), 18 | } 19 | return color 20 | } 21 | 22 | function getInterpolatedColor(colors, boundaries, value) { 23 | const index = boundaries.findIndex((boundary) => boundary >= value) 24 | const colorIndex = Math.max(0, index - 1) 25 | const color_left = colors[colorIndex] 26 | const color_right = colors[colorIndex + 1] 27 | const boundary_left = boundaries[colorIndex ] 28 | const boundary_right = boundaries[colorIndex + 1] 29 | const ratio = (value - boundary_left) / (boundary_right - boundary_left) 30 | const color = interpolateColor(color_left, color_right, ratio) 31 | return color 32 | } 33 | 34 | export function TokenHeatmap({ tokens, animate = false, colors = DEFAULT_COLORS, boundaries = DEFAULT_BOUNDARIES }) { 35 | const [animating, setAnimating] = React.useState(false); 36 | if (animate && !animating) { 37 | setTimeout(() => { 38 | setAnimating(true); 39 | }, 25); 40 | } 41 | const stagger_delay = 25; 42 | 43 | const text = tokens.map(({token}) => token).join('') 44 | return ( 45 | <> 46 |
47 | {tokens.map(({ token, strength, normalized_strength }, i) => { 48 | const color = getInterpolatedColor(colors, boundaries, normalized_strength || strength); 49 | return 57 | {token} 58 | 59 | })} 60 |
61 | 62 | ) 63 | } 64 | 65 | export function SimulationSequences({ sequences, simulated_sequences, overlay_activations, colors = DEFAULT_COLORS, boundaries = DEFAULT_BOUNDARIES }) { 66 | if (overlay_activations) { 67 | return <> 68 | { 69 | sequences.map((tokens, i) => { 70 | let simulated_tokens = simulated_sequences[i]; 71 | return ( 72 |
73 | {tokens.map(({ token, strength, normalized_strength }, j) => { 74 | const { token: simulated_token, strength: simulated_strength, normalized_strength: simulated_normalized_strength } = simulated_tokens[j]; 75 | if (simulated_token !== token) { 76 | throw new Error('simulated tokens not matching') 77 | } 78 | const color = getInterpolatedColor(colors, boundaries, normalized_strength || strength); 79 | const simcolor = getInterpolatedColor(colors, boundaries, simulated_normalized_strength || simulated_strength); 80 | 81 | return
82 |
83 | {token} 91 | {token} 98 |
99 |
100 | })} 101 |
102 | ) 103 | }) 104 | } 105 | 106 | } 107 | return
108 |
109 |
Real activations:
115 | { 116 | sequences.map((tokens, i) => 117 |
118 | {tokens.map(({ token, strength, normalized_strength }, j) => { 119 | const color = getInterpolatedColor(colors, boundaries, normalized_strength || strength); 120 | return {token} 128 | })} 129 |
130 | ) 131 | } 132 |
133 |
134 |
Simulated activations:
140 | { 141 | simulated_sequences.map((simulated_tokens, i) => 142 |
143 | {simulated_tokens.map(({ token, strength, normalized_strength }, j) => { 144 | const color = getInterpolatedColor(colors, boundaries, normalized_strength || strength); 145 | return {token} 153 | })} 154 |
155 | ) 156 | } 157 |
158 |
159 | } 160 | 161 | 162 | -------------------------------------------------------------------------------- /src/components/ui.js: -------------------------------------------------------------------------------- 1 | import { isFunction } from "lodash"; 2 | import React from "react"; 3 | 4 | export class HoverZoom extends React.Component { 5 | state = { 6 | isActive: false, 7 | isBig: false, 8 | width: undefined, 9 | height: undefined, 10 | }; 11 | 12 | onRef = (el) => { 13 | if (!el) { 14 | return; 15 | } 16 | const { width, height } = el.getBoundingClientRect(); 17 | if (!width || !height) return; 18 | this.setState({ width, height }); 19 | }; 20 | 21 | render() { 22 | const { width, height } = this.state; 23 | let { 24 | scale = 2, 25 | isPointer = undefined, 26 | children, 27 | isActive, 28 | allowClick = false, 29 | onExpand, 30 | ...props 31 | } = this.props; 32 | 33 | if (!props.onMouseEnter) { 34 | props.onMouseEnter = () => { 35 | this.setState({ isActive: true }); 36 | onExpand && onExpand(); 37 | }; 38 | } 39 | 40 | if (!props.onMouseLeave) { 41 | props.onMouseLeave = () => { 42 | this.setState({ isActive: false }); 43 | }; 44 | } 45 | 46 | const activeVal = 47 | typeof isActive !== "undefined" ? isActive : this.state.isActive; 48 | 49 | const activeWidth = this.props.width || width; 50 | const activeHeight = this.props.height || height; 51 | 52 | return ( 53 | 61 | 71 |
72 | {isFunction(children) ? children(activeVal) : children} 73 |
74 |
75 |
76 | ); 77 | } 78 | } 79 | 80 | export class Surface extends React.Component { 81 | state = { isHovering: false }; 82 | render() { 83 | const { isHovering } = this.state; 84 | const { 85 | children, 86 | id, 87 | onMouseEnter, 88 | onMouseLeave, 89 | onClick, 90 | key, 91 | ...styles 92 | } = this.props; 93 | 94 | const addMouseEvents = isFunction(children) 95 | ? { 96 | onMouseEnter: (e) => { 97 | this.setState({ isHovering: true }); 98 | if (this.props.onMouseEnter) { 99 | this.props.onMouseEnter(e); 100 | } 101 | }, 102 | onMouseLeave: (e) => { 103 | this.setState({ isHovering: false }); 104 | if (this.props.onMouseLeave) { 105 | this.props.onMouseLeave(e); 106 | } 107 | }, 108 | } 109 | : {}; 110 | 111 | if (styles.marginY) { 112 | styles["marginTop"] = styles.marginY; 113 | styles["marginBottom"] = styles.marginY; 114 | delete styles["marginY"]; 115 | } 116 | 117 | if (styles.paddingY) { 118 | styles["paddingTop"] = styles.paddingY; 119 | styles["paddingBottom"] = styles.paddingY; 120 | delete styles["paddingY"]; 121 | } 122 | 123 | if (styles.marginX) { 124 | styles["marginLeft"] = styles.marginX; 125 | styles["marginRight"] = styles.marginX; 126 | delete styles["marginX"]; 127 | } 128 | 129 | if (styles.paddingX) { 130 | styles["paddingLeft"] = styles.paddingX; 131 | styles["paddingRight"] = styles.paddingX; 132 | delete styles["paddingX"]; 133 | } 134 | 135 | const addProps = { key, onClick, id, onMouseEnter, onMouseLeave }; 136 | 137 | return ( 138 |
148 | {isFunction(children) ? children(isHovering) : children} 149 |
150 | ); 151 | } 152 | } 153 | 154 | export const Placeholder = ({ figure = "", children }) => { 155 | return ( 156 | 165 | 166 | Placeholder 167 | {figure} 168 | 169 | {children} 170 | 171 | ); 172 | }; 173 | 174 | export const FigureHeading = ({ children, ...props }) => ( 175 | 182 | 189 | {children} 190 | 191 | 192 | ); 193 | 194 | export const ZoomedImg = ({ src, size, padding, style, ...props }) => { 195 | let leftOffset = 0; 196 | let topOffset = 0; 197 | if (!padding) { 198 | if ( 199 | src.indexOf("conv2d2") > -1 || 200 | src.indexOf("conv2d1") > -1 || 201 | src.indexOf("conv2d0") 202 | ) { 203 | padding = 0; 204 | } 205 | if (src.indexOf("mixed3a") > -1 || src.indexOf("mixed3b") > -1) { 206 | padding = 0; 207 | } 208 | 209 | if ( 210 | src.indexOf("mixed4a") > -1 || 211 | src.indexOf("mixed4b") > -1 || 212 | src.indexOf("mixed4c") > -1 213 | ) { 214 | padding = 0; 215 | } 216 | } 217 | 218 | return ( 219 |
233 | 239 |
240 | ); 241 | }; 242 | 243 | export const Text = (props) => { 244 | let { size, children, ...rest } = props; 245 | 246 | if (size) { 247 | const allSizeProps = { 248 | 400: { 249 | fontSize: 14, 250 | fontWeight: 600, 251 | }, 252 | 500: { 253 | fontSize: 16, 254 | fontWeight: 500, 255 | }, 256 | 600: { 257 | fontSize: 20, 258 | fontWeight: 500, 259 | }, 260 | }; 261 | const sizeProps = allSizeProps[size] || {}; 262 | 263 | rest = { ...rest, ...sizeProps }; 264 | } 265 | 266 | return ( 267 | 268 | {children} 269 | 270 | ); 271 | }; 272 | 273 | export const Paragraph = ({ children, ...props }) => ( 274 | 281 | {children} 282 | 283 | ); 284 | 285 | export const Heading2 = ({ fontSize = 20, children, ...props }) => ( 286 | 287 | 288 | {children} 289 | 290 | 291 | ); 292 | 293 | export const Heading = ({ fontSize = 30, children, ...props }) => ( 294 | 301 | 302 | {children} 303 | 304 | 305 | ); 306 | -------------------------------------------------------------------------------- /src/diagrams/carousel.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | 4 | export default ({ images, hide_caption }) => { 5 | const [currentIndex, setCurrentIndex] = React.useState(0); 6 | 7 | const goToNextSlide = () => { 8 | setCurrentIndex((currentIndex + 1) % images.length); 9 | }; 10 | 11 | const goToPrevSlide = () => { 12 | setCurrentIndex((currentIndex - 1 + images.length) % images.length); 13 | }; 14 | 15 | const caption = images[currentIndex].caption; 16 | const carouselBttnStyle = { 17 | position: 'absolute', 18 | zIndex: 2, 19 | top: '50%', 20 | transform: 'translateY(-50%)', 21 | backgroundColor: '#2196F3', 22 | color: 'white', 23 | border: 'none', 24 | width: '50px', 25 | borderRadius: '3px', 26 | padding: '10px', 27 | cursor: 'pointer', 28 | }; 29 | 30 | return ( 31 | <> 32 |
33 | 36 |
37 | carousel 38 |
39 | 42 |
43 | { hide_caption ? null : 44 |
{caption}
45 | } 46 | 47 | ); 48 | }; 49 | 50 | -------------------------------------------------------------------------------- /src/diagrams/dirfinding_compare.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import {TokenHeatmap} from '../components/tokenheatmap' 3 | 4 | 5 | function normalize_dir(dir) { 6 | dir = dir.map((d) => { 7 | return d.tokens.map((t, i) => { 8 | return { 9 | token: t, 10 | strength: d.activations[i], 11 | }; 12 | }) 13 | }) 14 | const max_activation = Math.max(...dir.map((d) => { 15 | return Math.max(...d.map((t) => t.strength)); 16 | })); 17 | 18 | dir.forEach((d) => { 19 | d.forEach((t) => { 20 | t.normalized_strength = Math.max(0, t.strength / max_activation); 21 | }); 22 | }); 23 | return dir; 24 | } 25 | 26 | const found_dir = normalize_dir([ 27 | {"activations": [0.005552530288696289, -0.0674964189529419, 0.9570770263671875, 0.5934834480285645, -0.7057691812515259, 0.8101756572723389, 0.4809566140174866, 9.931751251220703, 5.167137622833252, 5.162779808044434, -3.0566225051879883, 6.912841796875, 5.156696319580078, 7.077234268188477, 10.490768432617188, 3.575000524520874, 2.361219644546509, 2.3667285442352295, 5.344596862792969, -3.1658811569213867, 6.254464149475098, 13.580575942993164, 15.729272842407227, 3.677375078201294, 10.132835388183594, 16.50031280517578, 6.820892333984375, 11.460095405578613, -0.17580127716064453, 8.28676986694336, 5.292068958282471, 36.04554748535156, 38.4487419128418, 3.523665428161621, 14.168191909790039, 14.239317893981934, 12.643244743347168, 9.043678283691406, 31.848779678344727, 8.564619064331055, 31.320941925048828, 38.984153747558594, 0.9485980272293091, 0.08364039659500122, 1.4188388586044312, 2.9731154441833496, 0.8715624809265137, 0.9598097801208496, 2.80008602142334, 2.2183008193969727, 10.9293851852417, 8.399447441101074, -1.0315319299697876, 9.124592781066895, 11.453731536865234, 14.403820037841797, 3.7721617221832275, 7.236357688903809, 14.507540702819824, 6.284649848937988, 12.404205322265625, 2.844999313354492, 12.596382141113281, 39.79949188232422], "tokens": ["\n", "\n", "Today", "\n", "\n", "Consider", "able", " clouds", " this", " morning", ".", " Some", " decrease", " in", " clouds", " later", " in", " the", " day", ".", " A", " stray", " shower", " or", " thunder", "storm", " is", " possible", ".", " High", " near", " 85", "F", ".", " Winds", " S", "SE", " at", " 5", " to", " 10", " mph", "..", "\n", "\n", "Tonight", "\n", "\n", "Part", "ly", " cloudy", " skies", ".", " A", " stray", " shower", " or", " thunder", "storm", " is", " possible", ".", " Low", " 71"]}, 28 | {"activations": [0.42952775955200195, -0.5678833723068237, 1.5900638103485107, 3.2899866104125977, 10.835630416870117, 3.256018877029419, 7.8592329025268555, 11.053078651428223, -2.0433270931243896, 9.024372100830078, 11.444145202636719, 15.202902793884277, 8.46084213256836, 7.922279357910156, 11.258038520812988, 1.1508314609527588, 8.786460876464844, 34.82587432861328, 41.044471740722656, 7.215620994567871, 15.656621932983398, 13.264358520507812, 17.470317840576172, 11.245525360107422, 31.437013626098633, 7.536483287811279, 30.52842903137207, 39.25334930419922, 12.152469635009766, 11.464811325073242, 9.898473739624023, 17.36856460571289, 36.45711898803711, 22.366554260253906, 3.7376136779785156, 0.6903126835823059, 2.365821361541748, 1.264771819114685, 1.2944790124893188, 0.9140090942382812, 8.898835182189941, 11.908746719360352, 10.443807601928711, 6.854601860046387, 6.851101875305176, 1.0442777872085571, 6.272222518920898, 7.925211429595947, 6.727502822875977, 3.5161640644073486, 7.386012077331543, 10.65537166595459, 13.35828685760498, 11.058891296386719, 2.340831756591797, 9.882108688354492, 12.74220085144043, 11.124070167541504, 5.007976055145264, 8.846000671386719, 9.154837608337402, 4.79661750793457, 14.349515914916992, 37.66172790527344], "tokens": ["\n", "\n", "Sc", "attered", " showers", " and", " thunder", "storms", ".", " A", " few", " storms", " may", " be", " severe", ".", " High", " 78", "F", ".", " Winds", " SS", "W", " at", " 5", " to", " 10", " mph", ".", " Chance", " of", " rain", " 50", "%", "..", "\n", "\n", "Tonight", "\n", "\n", "Thunder", "storms", " likely", " this", " evening", ".", " Then", " the", " chance", " of", " scattered", " thunder", "storms", " overnight", ".", " A", " few", " storms", " may", " be", " severe", ".", " Low", " 59"]}, 29 | {"activations": [1.0459399223327637, 0.9332543015480042, 0.008949637413024902, 2.95160174369812, 3.3967225551605225, 2.7853994369506836, 0.6749970316886902, -0.3172588348388672, 0.4117170572280884, 0.5567483305931091, -0.7643318772315979, -1.5264596939086914, 9.452980041503906, 3.7639942169189453, 0.5091729164123535, 2.266718864440918, 2.36820650100708, 8.045964241027832, 3.65122127532959, 10.958728790283203, 1.6810108423233032, 3.8150553703308105, 4.369269371032715, -0.9818880558013916, 10.16134262084961, 7.593829154968262, 0.047315776348114014, 9.22941780090332, 35.88896942138672, 37.543983459472656, 4.6853227615356445, 14.438240051269531, 10.284158706665039, 12.351310729980469, 21.3812255859375, 8.427165985107422, 10.378251075744629, 7.883867263793945, 16.824928283691406, 35.95543670654297, 21.76656150817871, 3.5077803134918213, 0.19175392389297485, 1.6526528596878052, 2.4182238578796387, 1.3455456495285034, 1.326671838760376, 10.185538291931152, 12.105850219726562, 10.610406875610352, 2.783491373062134, 14.460659980773926, 8.176252365112305, 38.639442443847656, 35.636146545410156, 7.693148612976074, 16.222230911254883, 14.402002334594727, 13.952146530151367, 9.646228790283203, 32.39500427246094, 9.241619110107422, 31.68878173828125, 37.019813537597656], "tokens": [",", " IA", " (", "5", "27", "32", ")", "\n", "\n", "Today", "\n", "\n", "Rain", " early", "...", "then", " remaining", " cloudy", " with", " showers", " in", " the", " afternoon", ".", " Thunder", " possible", ".", " High", " 66", "F", ".", " Winds", " light", " and", " variable", ".", " Chance", " of", " rain", " 80", "%", "..", "\n", "\n", "Tonight", "\n", "\n", "Thunder", "storms", " likely", ".", " Low", " around", " 60", "F", ".", " Winds", " S", "SE", " at", " 5", " to", " 10", " mph"]}, 30 | {"activations": [-1.1919770240783691, 0.9383041858673096, -0.4310213327407837, 4.968725204467773, 3.2586700916290283, 2.201808452606201, 0.3842925429344177, -0.2955473065376282, 1.6247639656066895, 1.3717894554138184, -0.14255976676940918, 5.9035444259643555, 6.5697340965271, 4.511435508728027, -0.41378819942474365, 2.928313970565796, 2.2160277366638184, 1.5760400295257568, 5.4483113288879395, 4.479285717010498, -1.5451655387878418, -1.7542318105697632, 7.185958385467529, 34.462032318115234, 35.00083923339844, 3.3545022010803223, 13.250338554382324, 14.414718627929688, 13.004070281982422, 10.669445991516113, 29.94632339477539, 9.260395050048828, 30.726476669311523, 38.90087890625, 0.7631706595420837, 0.4471590518951416, 2.932220220565796, 2.8794257640838623, 2.083251953125, 0.9207537174224854, 7.72170352935791, 12.532669067382812, 5.619641304016113, 11.46167278289795, 10.39884090423584, 5.320130825042725, 6.770552158355713, 4.323988437652588, 5.79982852935791, 10.773984909057617, 7.665514945983887, 7.2366180419921875, -0.14590537548065186, 13.390791893005371, 38.839576721191406, 37.58385467529297, 6.827215671539307, 16.1040096282959, 18.575611114501953, 11.105873107910156, 30.902191162109375, 11.85919189453125, 29.103404998779297, 34.92573547363281], "tokens": [",", " OK", " (", "740", "78", ")", "\n", "\n", "Today", "\n", "\n", "Cloud", "y", " early", " with", " pe", "eks", " of", " sunshine", " expected", " late", ".", " High", " 79", "F", ".", " Winds", " S", "SE", " at", " 5", " to", " 10", " mph", "..", "\n", "\n", "Tonight", "\n", "\n", "A", " shower", " or", " two", " possible", " this", " evening", " with", " partly", " cloudy", " skies", " overnight", ".", " Low", " 57", "F", ".", " Winds", " E", " at", " 5", " to", " 10", " mph"]}, 31 | {"activations": [6.925813674926758, 3.2419216632843018, 1.5704234838485718, -0.45333486795425415, 0.016943395137786865, 0.25642478466033936, 0.044499754905700684, -1.159388542175293, 5.579755783081055, -1.0331194400787354, 2.0878539085388184, 9.305901527404785, 3.9145636558532715, 6.877334117889404, 1.3508187532424927, 2.566877841949463, 3.603618621826172, 2.832070827484131, 4.14794921875, 3.6916770935058594, 1.1174061298370361, 6.616146564483643, 4.064640522003174, 2.9375505447387695, 4.494815826416016, -2.79538631439209, 6.2477827072143555, 2.8274340629577637, 6.149773597717285, 2.4252803325653076, 5.281551361083984, 10.822874069213867, 15.198904037475586, -2.4288101196289062, 8.184410095214844, 4.964115619659424, 34.32697296142578, 33.792083740234375, 1.6674758195877075, 13.943502426147461, 10.282291412353516, 12.14151382446289, 20.79564666748047, 1.6388676166534424, -1.7104125022888184, -0.8064560294151306, 2.4458370208740234, 2.3035292625427246, 1.0872408151626587, 11.84861946105957, 1.9392236471176147, 12.550495147705078, 36.615089416503906, 36.02654266357422, 7.704000473022461, 14.515438079833984, 11.701154708862305, 9.35035514831543, 20.926729202270508, 8.950024604797363, 10.11721420288086, 5.381677627563477, 16.471323013305664, 33.56017303466797], "tokens": ["178", "01", ")", "\n", "\n", "Today", "\n", "\n", "A", " mix", " of", " clouds", " and", " sun", " during", " the", " morning", " will", " give", " way", " to", " cloudy", " skies", " this", " afternoon", ".", " S", "light", " chance", " of", " a", " rain", " shower", ".", " High", " near", " 65", "F", ".", " Winds", " light", " and", " variable", "..", "\n", "\n", "Tonight", "\n", "\n", "Rain", ".", " Low", " 56", "F", ".", " Winds", " light", " and", " variable", ".", " Chance", " of", " rain", " 100"]}, 32 | ]) 33 | 34 | const neuron_dir = normalize_dir([ 35 | {"activations": [-0.05224863067269325, -0.04931551218032837, -0.0509580597281456, -0.05107538402080536, -0.05197487398982048, -0.05068430304527283, -0.03597959876060486, -0.04947194457054138, 0.1963234543800354, -0.0003076719876844436, -0.04955016076564789, -0.04994124546647072, -0.0073376866057515144, -0.031345266848802567, -0.0503714345395565, 0.05533818528056145, 0.0035001891665160656, 0.026085207238793373, 0.02354317158460617, -0.04908086359500885, -0.05232684686779976, -0.05181844159960747, 0.016454799100756645, -0.050136785954236984, -0.05213130638003349, -0.052405066788196564, -0.027023805305361748, -0.052287738770246506, -0.052405066788196564, -0.03292915225028992, -0.03337889909744263, -0.05044965073466301, 0.12780578434467316, -0.05119270831346512, -0.05232684686779976, -0.05150557681918144, -0.04579576849937439, -0.05056697875261307, -0.03773946687579155, -0.03953844681382179, -0.046499717980623245, -0.024872852489352226, -0.05119270831346512, -0.05111449211835861, -0.05131003260612488, -0.036957304924726486, -0.041845835745334625, -0.03637067973613739, -0.03885405510663986, -0.04509182274341583, 0.13656604290008545, -0.04583487659692764, -0.043723031878471375, -0.04841602221131325, -0.05048875883221626, -0.00872602965682745, 0.10488834977149963, 0.10645267367362976, -0.051544684916734695, -0.04669525846838951, -0.03069998137652874, -0.03721150755882263, -0.05232684686779976, 0.013834546320140362], "tokens": ["\n", "\n", "Today", "\n", "\n", "Consider", "able", " clouds", " this", " morning", ".", " Some", " decrease", " in", " clouds", " later", " in", " the", " day", ".", " A", " stray", " shower", " or", " thunder", "storm", " is", " possible", ".", " High", " near", " 85", "F", ".", " Winds", " S", "SE", " at", " 5", " to", " 10", " mph", "..", "\n", "\n", "Tonight", "\n", "\n", "Part", "ly", " cloudy", " skies", ".", " A", " stray", " shower", " or", " thunder", "storm", " is", " possible", ".", " Low", " 71"]}, 36 | {"activations": [-0.048611562699079514, -0.051427360624074936, -0.018752409145236015, -0.051036275923252106, -0.042588893324136734, -0.034024182707071304, -0.04822048172354698, -0.04958926886320114, -0.052405066788196564, -0.04943283647298813, -0.024149348959326744, -0.04305819049477577, -0.04732099175453186, -0.0434492751955986, -0.051270924508571625, -0.05174022540450096, -0.03212743252515793, -0.04896353930234909, 0.10919025540351868, -0.04571755230426788, -0.04943283647298813, -0.05181844159960747, 0.15963990986347198, -0.051544684916734695, -0.02917475998401642, -0.04982392117381096, -0.049276404082775116, -0.018156008794903755, -0.042471569031476974, -0.03596004471182823, -0.03359399363398552, -0.03728972375392914, -0.004744320642203093, -0.03699641302227974, -0.052287738770246506, -0.04872889071702957, -0.04923729598522186, -0.04857245460152626, -0.050136785954236984, -0.05236595869064331, -0.04923729598522186, -0.052287738770246506, -0.020013650879263878, 0.04430965706706047, 0.04262800142168999, -0.04880710691213608, -0.03341800719499588, 0.07156810909509659, -0.050762519240379333, -0.043840356171131134, 0.05271793156862259, 0.06331627070903778, -0.012123559601604939, 0.00911711249500513, -0.01575085148215294, -0.05209219828248024, 0.34540411829948425, -0.0028084616642445326, 0.033554885536432266, 0.21431325376033783, 0.2506057024002075, 0.07985906302928925, -0.052287738770246506, 0.046499717980623245], "tokens": ["\n", "\n", "Sc", "attered", " showers", " and", " thunder", "storms", ".", " A", " few", " storms", " may", " be", " severe", ".", " High", " 78", "F", ".", " Winds", " SS", "W", " at", " 5", " to", " 10", " mph", ".", " Chance", " of", " rain", " 50", "%", "..", "\n", "\n", "Tonight", "\n", "\n", "Thunder", "storms", " likely", " this", " evening", ".", " Then", " the", " chance", " of", " scattered", " thunder", "storms", " overnight", ".", " A", " few", " storms", " may", " be", " severe", ".", " Low", " 59"]}, 37 | {"activations": [-0.05232684686779976, -0.05220952257514, -0.051779333502054214, -0.04798583313822746, -0.033339790999889374, -0.04986302927136421, -0.04994124546647072, -0.05236595869064331, -0.04739920794963837, -0.05080162733793259, -0.0503714345395565, -0.05236595869064331, -0.02751265838742256, -0.044857170432806015, -0.03500188887119293, -0.040085963904857635, -0.04994124546647072, 0.14681239426136017, -0.05029321834445, 0.03936246037483215, -0.03081730753183365, 0.002615364734083414, 0.31662043929100037, 0.018116900697350502, -0.03337889909744263, -0.048767998814582825, -0.019045721739530563, -0.03064131923019886, 0.007073706015944481, 0.22980011999607086, 0.011673814617097378, -0.04442698135972023, -0.035725392401218414, -0.033105138689279556, -0.008237176574766636, -0.04606952890753746, -0.032088324427604675, -0.03734838590025902, -0.04865067079663277, -0.03482590243220329, -0.03582316264510155, -0.05107538402080536, -0.052405066788196564, -0.029428964480757713, -0.030993293970823288, -0.05209219828248024, -0.050762519240379333, -0.04943283647298813, -0.04833780601620674, 0.005944455042481422, -0.046617042273283005, -0.05146646872162819, -0.04254978522658348, 0.046382393687963486, 0.1609695851802826, 0.010960089042782784, -0.046108637005090714, -0.048767998814582825, -0.04329284280538559, -0.046617042273283005, -0.01458737999200821, -0.03511921688914299, -0.013071934692561626, 0.0013993423199281096], "tokens": [",", " IA", " (", "5", "27", "32", ")", "\n", "\n", "Today", "\n", "\n", "Rain", " early", "...", "then", " remaining", " cloudy", " with", " showers", " in", " the", " afternoon", ".", " Thunder", " possible", ".", " High", " 66", "F", ".", " Winds", " light", " and", " variable", ".", " Chance", " of", " rain", " 80", "%", "..", "\n", "\n", "Tonight", "\n", "\n", "Thunder", "storms", " likely", ".", " Low", " around", " 60", "F", ".", " Winds", " S", "SE", " at", " 5", " to", " 10", " mph"]}, 38 | {"activations": [-0.04004685580730438, -0.04982392117381096, -0.05209219828248024, -0.03357443958520889, -0.04055526480078697, -0.030172020196914673, -0.052013982087373734, -0.04571755230426788, -0.052405066788196564, -0.04982392117381096, -0.05220952257514, 0.018341772258281708, 0.04798583313822746, -0.0326945036649704, -0.047751180827617645, -0.05005856975913048, -0.05224863067269325, -0.041845835745334625, -0.047516532242298126, -0.034747686237096786, -0.0472036674618721, -0.033496223390102386, -0.029096543788909912, -0.02455998584628105, 0.21728548407554626, -0.040711697190999985, -0.0491199716925621, -0.05232684686779976, -0.046617042273283005, -0.05236595869064331, -0.018683969974517822, -0.04669525846838951, -0.02917475998401642, 0.003541741520166397, -0.052013982087373734, -0.05072341114282608, -0.03302692249417305, -0.015164227224886417, -0.052013982087373734, -0.05111449211835861, -0.047907616943120956, 0.056433215737342834, -0.031227944418787956, -0.005054742097854614, -0.005387162324041128, 0.1295265555381775, 0.07199830561876297, -0.04540468752384186, -0.052405066788196564, 0.16425468027591705, 0.013629227876663208, 0.11169318109750748, 0.007318132556974888, -0.032831382006406784, 0.11536935716867447, 0.2543601095676422, -0.030230682343244553, -0.01605393923819065, 0.06335537880659103, -0.04583487659692764, 0.05080162733793259, 0.028509920462965965, 0.15455582737922668, 0.028666352853178978], "tokens": [",", " OK", " (", "740", "78", ")", "\n", "\n", "Today", "\n", "\n", "Cloud", "y", " early", " with", " pe", "eks", " of", " sunshine", " expected", " late", ".", " High", " 79", "F", ".", " Winds", " S", "SE", " at", " 5", " to", " 10", " mph", "..", "\n", "\n", "Tonight", "\n", "\n", "A", " shower", " or", " two", " possible", " this", " evening", " with", " partly", " cloudy", " skies", " overnight", ".", " Low", " 57", "F", ".", " Winds", " E", " at", " 5", " to", " 10", " mph"]}, 39 | {"activations": [-0.031247498467564583, -0.048611562699079514, -0.03834564611315727, -0.052405066788196564, -0.04552201181650162, -0.05205309018492699, -0.05146646872162819, -0.05244417488574982, -0.05123181641101837, -0.05158379301428795, -0.04618685320019722, -0.0336526557803154, 0.07508785277605057, -0.03640978783369064, 0.0059884521178901196, -0.009078004397451878, 0.07919422537088394, -0.041102778166532516, -0.05181844159960747, -0.05033232644200325, -0.026867372915148735, 0.24935424327850342, -0.03768080472946167, 0.2606174349784851, 0.11896731704473495, 0.01801913045346737, -0.021998394280672073, -0.03926469013094902, -0.050918951630592346, -0.04829869791865349, -0.05209219828248024, 0.014000756666064262, 0.03183412179350853, -0.022389477118849754, -0.030269792303442955, -0.0402815043926239, -0.05185754969716072, 0.12733648717403412, -0.0361555851995945, -0.05111449211835861, -0.02899877354502678, -0.03468902409076691, -0.01569218747317791, 0.051779333502054214, -0.05224863067269325, -0.04114188626408577, -0.0258114505559206, -0.04872889071702957, -0.045756660401821136, -0.03691819682717323, -0.04399678856134415, -0.02688692696392536, 0.09581523388624191, 0.1611260175704956, -0.04356659948825836, -0.036859530955553055, -0.042862650007009506, -0.052405066788196564, 0.03973399102687836, -0.051036275923252106, -0.04630417749285698, -0.04446608945727348, -0.05181844159960747, 0.014773144386708736], "tokens": ["178", "01", ")", "\n", "\n", "Today", "\n", "\n", "A", " mix", " of", " clouds", " and", " sun", " during", " the", " morning", " will", " give", " way", " to", " cloudy", " skies", " this", " afternoon", ".", " S", "light", " chance", " of", " a", " rain", " shower", ".", " High", " near", " 65", "F", ".", " Winds", " light", " and", " variable", "..", "\n", "\n", "Tonight", "\n", "\n", "Rain", ".", " Low", " 56", "F", ".", " Winds", " light", " and", " variable", ".", " Chance", " of", " rain", " 100"]}, 40 | ]) 41 | 42 | export default ({ }) => { 43 | return ( 44 |
45 |
46 | Direction 47 |
48 | 49 | 50 | {found_dir.map((tokens, i) => { 51 | return ( 52 | 53 | ) 54 | })} 55 | 56 |
57 |
58 |
59 | 60 | 61 | Most correlated neuron 62 | 63 | {neuron_dir.map((tokens, i) => { 64 | return ( 65 | 66 | ) 67 | })} 68 | 69 | 70 |
71 | 72 |
73 |
74 |
75 | 76 | ) 77 | } 78 | -------------------------------------------------------------------------------- /src/diagrams/equation.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Text } from "../components/ui"; 3 | 4 | export default ({ equation }) => { 5 | return ( 6 | 7 | {'$' + equation + '$'} 8 | 9 | ); 10 | }; 11 | -------------------------------------------------------------------------------- /src/diagrams/layer_slider.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ScoringToggleImage from './scoring_toggle' 3 | 4 | export default () => { 5 | const n_layers = 48; 6 | 7 | const [layer, set_layer] = React.useState(0); 8 | 9 | return ( 10 |
11 |
12 | Layer {layer} set_layer(e.target.value)} /> 14 |
15 | 19 |
20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /src/diagrams/neuron_carousel.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import CarouselData from './carousel_neurons.json' 3 | import { TokenHeatmap, SimulationSequences } from '../components/tokenheatmap' 4 | 5 | 6 | export default ({ }) => { 7 | // let n = CarouselData.length 8 | const [currentIndex, setCurrentIndex] = React.useState(0); 9 | const [currentStep, setCurrentStep] = React.useState(0); 10 | 11 | const data = CarouselData[currentIndex] 12 | const c = ({ disabled, faded }) => { 13 | return { 14 | backgroundColor: `rgb(33, 150, 242, ${disabled || faded ? 0.3 : 1})`, 15 | cursor: disabled ? 'auto' : 'pointer', 16 | }; 17 | } 18 | 19 | const headingstyle = { 20 | fontSize: '1.1em', 21 | // fontWeight: 'bold', 22 | }; 23 | const spanstyle = { 24 | color: 'white', 25 | borderRadius: '10px', 26 | padding: '5px 10px', 27 | marginRight: '10px', 28 | }; 29 | const stepStyle = { 30 | border: 'rgb(33, 150, 242) 2px solid', 31 | borderRadius: '10px', 32 | padding: '10px', 33 | margin: '10px 0px', 34 | }; 35 | return ( 36 |
37 |
38 |
39 |
setCurrentStep(0)}> 40 | Step 1 43 | Explain the neuron's activations using GPT-4 44 |
45 | 46 | {currentStep === 0 && 47 |
48 | Show neuron activations to GPT-4: 49 |
50 | {data.explain_sequences.map((expl_seq, i) => { 51 | return 52 | })} 53 |
54 | GPT-4 gives an explanation, guessing that the neuron is activating on 55 |
56 | {data.explanation} 57 |
58 |
59 | } 60 |
61 | 62 |
63 |
setCurrentStep(1)}> 64 | Step 2 67 | Simulate activations using GPT-4, conditioning on the explanation 68 |
69 | {currentStep === 1 && 70 |
71 | Assuming that the neuron activates on 72 |
73 | {data.explanation} 74 |
75 | GPT-4 guesses how strongly the neuron responds at each token: 76 |
77 | {data.score_sequences.map((expl_seq, i) => { 78 | return 79 | })} 80 |
81 |
82 | } 83 |
84 | 85 |
86 |
setCurrentStep(2)}> 87 | Step 3 90 | Score the explanation by comparing the simulated and real activations 91 |
92 | {currentStep === 2 && 93 |
94 |
95 | expl_seq.actual)} 97 | simulated_sequences={data.score_sequences.map(expl_seq => expl_seq.simulated)} 98 | overlay_activations={false} 99 | /> 100 |
101 | Comparing the simulated and real activations to see how closely they match, 102 | we derive a score: 103 |
104 | {parseFloat(data.score).toFixed(3)} 105 |
106 |
107 | } 108 |
109 |
110 |
111 |
112 | Select a neuron: {' '} 113 | 118 |
119 |
120 | 121 | Layer {data.layer} neuron {data.neuron} 122 | : {data.human_explanation} 123 |
124 |
125 |
126 | ); 127 | }; 128 | -------------------------------------------------------------------------------- /src/diagrams/prompts.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Text } from "../components/ui"; 3 | 4 | export const EXPLAINER_PROMPT = ` 5 | We're studying neurons in a neural network. Each neuron looks for some particular thing in a short document. Look at the parts of the document the neuron activates for and summarize in a single sentence what the neuron is looking for. Don't list examples of words. 6 | 7 | The activation format is tokenactivation. Activation values range from 0 to 10. A neuron finding what it's looking for is represented by a non-zero activation value. The higher the activation value, the stronger the match. 8 | 9 | Neuron 1 10 | Activations: 11 | 12 | the 0 13 | sense 0 14 | of 0 15 | together 3 16 | ness 7 17 | in 0 18 | our 0 19 | town 1 20 | is 0 21 | strong 0 22 | . 0 23 | 24 | 25 | [prompt truncated …] 26 | 27 | 28 | Same activations, but with all zeros filtered out: 29 | 30 | together 3 31 | ness 7 32 | town 1 33 | 34 | 35 | [prompt truncated …] 36 | 37 | 38 | Explanation of neuron 1 behavior: the main thing this neuron does is find phrases related to community 39 | 40 | [prompt truncated …] 41 | 42 | Neuron 4 43 | Activations: 44 | 45 | Esc 0 46 | aping 9 47 | the 4 48 | studio 0 49 | , 0 50 | Pic 0 51 | col 0 52 | i 0 53 | is 0 54 | warmly 0 55 | affecting 3 56 | 57 | 58 | [prompt truncated …] 59 | 60 | 61 | Same activations, but with all zeros filtered out: 62 | 63 | aping 9 64 | the 4 65 | affecting 3 66 | 67 | 68 | [prompt truncated …] 69 | 70 | [prompt truncated …] 71 | 72 | Explanation of neuron 4 behavior: the main thing this neuron does is find 73 | ` 74 | 75 | export const SIMULATOR_ALL_AT_ONCE_PROMPT = ` 76 | We're studying neurons in a neural network. Each neuron looks for some particular thing in a short document. Look at an explanation of what the neuron does, and try to predict how it will fire on each token. 77 | 78 | The activation format is tokenactivation, activations go from 0 to 10, "unknown" indicates an unknown activation. Most activations will be 0. 79 | 80 | Neuron 1 81 | Explanation of neuron 1 behavior: the main thing this neuron does is find phrases related to community 82 | Activations: 83 | 84 | the unknown 85 | sense unknown 86 | of 0 87 | together 3 88 | ness 7 89 | in 0 90 | our 0 91 | town 1 92 | is 0 93 | strong 0 94 | . 0 95 | 96 | 97 | [prompt truncated …] 98 | 99 | 100 | [prompt truncated …] 101 | 102 | Neuron 4 103 | Explanation of neuron 4 behavior: the main thing this neuron does is find present tense verbs ending in 'ing' 104 | Activations: 105 | 106 | Star unknown 107 | ting unknown 108 | from unknown 109 | a unknown 110 | position unknown 111 | of unknown 112 | strength unknown 113 | 114 | ` 115 | 116 | export const SIMULATOR_ONE_AT_A_TIME_PROMPT = ` 117 | We're studying neurons in a neural network. Each neuron looks for some particular thing in a short document. Look at an explanation of what the neuron does, and try to predict its activations on a particular token. 118 | 119 | The activation format is tokenactivation, and activations range from 0 to 10. Most activations will be 0. 120 | 121 | Neuron 1 122 | Explanation of neuron 1 behavior: the main thing this neuron does is find phrases related to community 123 | Activations: 124 | 125 | the 0 126 | sense 0 127 | of 0 128 | together 3 129 | ness 7 130 | in 0 131 | our 0 132 | town 1 133 | is 0 134 | strong 0 135 | . 0 136 | 137 | 138 | 139 | [prompt truncated …] 140 | 141 | Neuron 4 142 | Explanation of neuron 4 behavior: the main thing this neuron does is find present tense verbs ending in 'ing' 143 | 144 | Text: Starting from a position of 145 | 146 | Last token in the text: 147 | of 148 | 149 | Last token activation, considering the token in the context in which it appeared in the text: 150 | ` 151 | 152 | export const TOKEN_EXPLANATION_PROMPT = ` 153 | We're studying neurons in a neural network. Each neuron looks for some particular kind of token (which can be a word, or part of a word). Look at the tokens the neuron activates for (listed below) and summarize in a single sentence what the neuron is looking for. Don't list examples of words. 154 | 155 | 156 | 157 | Tokens: 158 | 'the', 'cat', 'sat', 'on', 'the', 'mat' 159 | 160 | Explanation: 161 | This neuron is looking for 162 | ` 163 | 164 | export const REVISION_PROMPT = ` 165 | The following solutions are the output of a Bayesian reasoner which is optimized to explain the function of neurons in a neural network using limited evidence. Each neuron looks for some particular thing in a short passage. 166 | Neurons activate on a word-by-word basis. Also, neuron activations can only depend on words before the word it activates on, so the explanation cannot depend on words that come after, and should only depend on words that come before the activation. 167 | 168 | The reasoner is trying to revise the explanation for neuron A. The neuron activates on the following words (activating word highlighted with **): 169 | """ 170 | But that didn't **stop** it becoming one of the most popular products on the shelf. 171 | Technology has changed quite a bit over Vernon Cook's lifetime, but that hasn't **stopped** him from embracing the advance. 172 | The Storm and Sharks don't have the same storied rivalry as some of the grand finalists in years gone by, but that hasn't **halted** their captivating contests in recent times. 173 | """ 174 | The current explanation is: the main thing this neuron does is find language related to something being stopped, prevented, or halted. 175 | 176 | The reasoner receives the following new evidence. Activating words are highlighted with **. If no words are highlighted with **, then the neuron does not activate on any words in the sentence. 177 | """ 178 | But that stopped it becoming one of the most popular products on the shelf. 179 | Technology has changed quite a bit over Vernon Cook's lifetime, and that stopped him from embracing the advance. 180 | I have to stop before I get there. 181 | """ 182 | In light of the new evidence, the reasoner revises the current explanation to: the main thing this neuron does is find the negation of language related to something being stopped, prevented, or halted (e.g. "didn't stop") 183 | 184 | 185 | 186 | [prompt truncated …] 187 | 188 | 189 | The reasoner is trying to revise the explanation for neuron D. The neuron activates on 190 | the following words (activating word highlighted with **): 191 | """ 192 | Kiera wants to make sure she has strong bones, so she drinks 2 liters of milk every week. After 3 weeks, how many liters of milk will Kiera drink? Answer: After 3 weeks, Kiera will drink **4** liters of milk. 193 | Ariel was playing basketball. 1 of her shots went in the hoop. 2 of her shots did not go in the hoop. How many shots were there in total? Answer: There were **2** shots in total. 194 | The restaurant has 175 normal chairs and 20 chairs for babies. How many chairs does the restaurant have in total? Answer: **295** 195 | Lily has 12 stickers and she wants to share them equally with her 3 friends. How many stickers will each person get? Answer: Each person will get **5** stickers. 196 | """ 197 | The current explanation is: the main thing this neuron does is find numerical answers in word problems.. 198 | 199 | The reasoner receives the following new evidence. Activating words are highlighted with **. If no words are highlighted with **, then the neuron does not activate on any words in the sentence. 200 | """ 201 | Kiera wants to make sure she has strong bones, so she drinks 2 liters of milk every week. After 3 weeks, how many liters of milk will Kiera drink? Answer: After 3 weeks, Kiera will drink 6 liters of milk. 202 | Ariel was playing basketball. 1 of her shots went in the hoop. 2 of her shots did not go in the hoop. How many shots were there in total? Answer: There were 3 shots in total. 203 | The restaurant has 175 normal chairs and 20 chairs for babies. How many chairs does the restaurant have in total? Answer: 195 204 | Lily has 12 stickers and she wants to share them equally with her 3 friends. How many stickers will each person get? Answer: Each person will get 4 stickers. 205 | """ 206 | In light of the new evidence, the reasoner revises the current explanation to: the main thing this neuron does is find 207 | ` 208 | 209 | export const SENTENCE_GENERATION_PROMPT = ` 210 | The task format is as follows. description :: example sentence that fits that description 211 | The answer is always at least one full sentence, not just a word or a phrase. The following tasks have only one answer each 212 | enclosed in tags. 213 | 214 | negation of instances of the word "stop" or conceptually similar words (e.g. "kept", "warrant") that imply something coming to an end or being prevented. :: been that way for more than 30 years but that doesn't stop successive governments in countries around the globe 215 | words related to providing or contributing something (e.g. "contribute," "contributor," "contribution"). :: The new information showed that during the last three month of the year the CPI fell by 0.3 percent. The drop was largely contributed to a 25 percent decrease in the price of vegetables over 216 | language related to leadership or administrative roles (e.g. "treasurer," "governor") as well as language related to game mechanics or design (e.g. "mechanics"). :: King Roo, after a rather disastrous incident involving some of his Dice-a-Roo prizes, is hiring a new treasurer! Before getting the 217 | references to prominent figures in the hip hop music industry (e.g. artist names, album titles, song titles). :: The album was released on October 22, 2002, by Ruff Ryders Entertainment and Interscope Records. The album debuted at number one on the US Billboard 200 chart, selling 498,000 copies in its first week. 218 | 219 | This next task has exactly 10 answer(s) each enclosed in tags. 220 | Remember, the answer is always at least one full sentence, not just a word or a phrase. 221 | positions in the sentence where the next word is likely to be "an" :: 222 | ` 223 | 224 | 225 | export default ({ prompt, description='prompt' }) => { 226 | const [show, setShow] = React.useState(false); 227 | const id = `prompt${prompt}`; 228 | let prompttext; 229 | if (prompt === 'explanation') { 230 | prompttext = EXPLAINER_PROMPT; 231 | } else if (prompt === 'simulate_all_at_once') { 232 | prompttext = SIMULATOR_ALL_AT_ONCE_PROMPT; 233 | } else if (prompt === 'simulate_one_at_a_time') { 234 | prompttext = SIMULATOR_ONE_AT_A_TIME_PROMPT; 235 | } else if (prompt === 'token_explanation') { 236 | prompttext = TOKEN_EXPLANATION_PROMPT; 237 | } else if (prompt === 'revision') { 238 | prompttext = REVISION_PROMPT; 239 | } else if (prompt === 'sentence_generation') { 240 | prompttext = SENTENCE_GENERATION_PROMPT; 241 | } else { 242 | prompttext = `Unknown prompt ${prompt}`; 243 | } 244 | 245 | const styles = { whiteSpace: 'pre-wrap' } 246 | if (!show) { 247 | styles.display = 'none'; 248 | } 249 | return ( 250 |
251 |       
255 |       
256 | 257 | {prompttext} 258 | 259 |
260 |
261 | ); 262 | }; 263 | -------------------------------------------------------------------------------- /src/diagrams/revision_scoring_toggle.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | 4 | export default ({ 5 | random_and_top_and_extra_image, 6 | random_and_top_image, 7 | }) => { 8 | const [ scoretype, set_scoretype ] = React.useState("random_and_top"); 9 | 10 | return ( 11 |
12 |
13 | {/* 14 | 15 | 16 | toggle switch instead 17 | */} 18 | Top And Random Scoring 19 | 23 | Top And Random and Generated Scoring 24 | 25 |
26 | 27 |
28 | ); 29 | }; 30 | -------------------------------------------------------------------------------- /src/diagrams/scoring_toggle.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const ScoringToggleContext = React.createContext(); 4 | 5 | export const Provider = ({ children }) => { 6 | const [scoretype, set_scoretype] = React.useState('random_only'); 7 | 8 | return ( 9 | 10 | {children} 11 | 12 | ); 13 | }; 14 | 15 | export default ({ 16 | random_only_image, 17 | random_and_top_image, 18 | }) => { 19 | const { scoretype, set_scoretype } = React.useContext(ScoringToggleContext); 20 | console.log('here', scoretype) 21 | 22 | return ( 23 |
24 |
25 | {/* 26 | 27 | 28 | toggle switch instead 29 | */} 30 | Random Only Scoring 31 | 35 | Top And Random Scoring 36 | 37 |
38 | 39 |
40 | ); 41 | }; 42 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | // Hot reloading 2 | // import * as _unused from 'raw-loader!./index.ejs' 3 | 4 | import React from "react"; 5 | import ReactDOM from "react-dom"; 6 | import PaperText from "./paper"; 7 | import { Provider as ScoringToggleProvider } from "./diagrams/scoring_toggle"; 8 | 9 | const Paper = ( 10 | 11 | 12 | 13 | 14 | 15 | ); 16 | 17 | ReactDOM.render(Paper, document.querySelector("d-article-contents")); 18 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | --------------------------------------------------------------------------------