Converted CRA packages to Vite
refs https://github.com/TryGhost/DevOps/issues/50 - we're moving away from CRA in favor of Vite, so this switches the last packages over
This commit is contained in:
parent
145d0b84f5
commit
5875962392
6
.github/scripts/dev.js
vendored
6
.github/scripts/dev.js
vendored
@ -108,7 +108,7 @@ if (DASH_DASH_ARGS.includes('announcement-bar') || DASH_DASH_ARGS.includes('anno
|
|||||||
prefixColor: '#DC9D00',
|
prefixColor: '#DC9D00',
|
||||||
env: {}
|
env: {}
|
||||||
});
|
});
|
||||||
COMMAND_GHOST.env['announcementBar__url'] = 'http://localhost:5371/announcement-bar';
|
COMMAND_GHOST.env['announcementBar__url'] = 'http://localhost:4177/announcement-bar.min.js';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DASH_DASH_ARGS.includes('search') || DASH_DASH_ARGS.includes('all')) {
|
if (DASH_DASH_ARGS.includes('search') || DASH_DASH_ARGS.includes('all')) {
|
||||||
@ -119,8 +119,8 @@ if (DASH_DASH_ARGS.includes('search') || DASH_DASH_ARGS.includes('all')) {
|
|||||||
prefixColor: '#23de43',
|
prefixColor: '#23de43',
|
||||||
env: {}
|
env: {}
|
||||||
});
|
});
|
||||||
COMMAND_GHOST.env['sodoSearch__url'] = 'http://localhost:5370/umd/sodo-search.min.js';
|
COMMAND_GHOST.env['sodoSearch__url'] = 'http://localhost:4178/sodo-search.min.js';
|
||||||
COMMAND_GHOST.env['sodoSearch__styles'] = 'http://localhost:5370/umd/main.css';
|
COMMAND_GHOST.env['sodoSearch__styles'] = 'http://localhost:4178/main.css';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DASH_DASH_ARGS.includes('lexical')) {
|
if (DASH_DASH_ARGS.includes('lexical')) {
|
||||||
|
@ -70,7 +70,6 @@
|
|||||||
"@vitejs/plugin-react": "4.0.3",
|
"@vitejs/plugin-react": "4.0.3",
|
||||||
"autoprefixer": "10.4.14",
|
"autoprefixer": "10.4.14",
|
||||||
"concurrently": "8.2.0",
|
"concurrently": "8.2.0",
|
||||||
"eslint-config-react-app": "7.0.1",
|
|
||||||
"eslint-plugin-react-hooks": "4.6.0",
|
"eslint-plugin-react-hooks": "4.6.0",
|
||||||
"eslint-plugin-react-refresh": "0.4.3",
|
"eslint-plugin-react-refresh": "0.4.3",
|
||||||
"eslint-plugin-tailwindcss": "3.13.0",
|
"eslint-plugin-tailwindcss": "3.13.0",
|
||||||
|
@ -1,82 +1,15 @@
|
|||||||
# Announcement Bar
|
# Announcement Bar
|
||||||
|
|
||||||
# Getting Started with Create React App
|
## Development
|
||||||
|
|
||||||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
### Pre-requisites
|
||||||
|
|
||||||
## Basic Setup
|
- Run `yarn` in Ghost monorepo root
|
||||||
|
- Run `yarn` in this directory
|
||||||
|
|
||||||
This section is mostly relevant for core team only for active development.
|
### Running via Ghost `yarn dev` in root folder
|
||||||
|
|
||||||
Run `yarn dev` with `--announcement-bar` to start Ghost with a development version of Announcement Bar
|
|
||||||
|
|
||||||
## Available Scripts
|
|
||||||
|
|
||||||
In the project directory, you can run:
|
|
||||||
|
|
||||||
### `yarn start`
|
|
||||||
|
|
||||||
Runs the app in the development mode.\
|
|
||||||
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
|
|
||||||
|
|
||||||
The page will reload when you make changes.\
|
|
||||||
You may also see any lint errors in the console.
|
|
||||||
|
|
||||||
### `yarn test`
|
|
||||||
|
|
||||||
Launches the test runner in the interactive watch mode.\
|
|
||||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
|
||||||
|
|
||||||
### `yarn build`
|
|
||||||
|
|
||||||
Builds the app for production to the `build` folder.\
|
|
||||||
It correctly bundles React in production mode and optimizes the build for the best performance.
|
|
||||||
|
|
||||||
The build is minified and the filenames include the hashes.\
|
|
||||||
Your app is ready to be deployed!
|
|
||||||
|
|
||||||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
|
||||||
|
|
||||||
### `yarn eject`
|
|
||||||
|
|
||||||
**Note: this is a one-way operation. Once you `eject`, you can't go back!**
|
|
||||||
|
|
||||||
If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
|
||||||
|
|
||||||
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
|
|
||||||
|
|
||||||
You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
|
|
||||||
|
|
||||||
## Learn More
|
|
||||||
|
|
||||||
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
|
||||||
|
|
||||||
To learn React, check out the [React documentation](https://reactjs.org/).
|
|
||||||
|
|
||||||
### Code Splitting
|
|
||||||
|
|
||||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
|
|
||||||
|
|
||||||
### Analyzing the Bundle Size
|
|
||||||
|
|
||||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
|
|
||||||
|
|
||||||
### Making a Progressive Web App
|
|
||||||
|
|
||||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
|
|
||||||
|
|
||||||
### Advanced Configuration
|
|
||||||
|
|
||||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
|
|
||||||
|
|
||||||
### Deployment
|
|
||||||
|
|
||||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
|
|
||||||
|
|
||||||
### `yarn build` fails to minify
|
|
||||||
|
|
||||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
|
|
||||||
|
|
||||||
|
You can automatically start the announcement-bar dev server when developing Ghost by running Ghost (in root folder) via `yarn dev --announcementbar`.
|
||||||
|
|
||||||
# Copyright & License
|
# Copyright & License
|
||||||
|
|
||||||
|
@ -17,32 +17,22 @@
|
|||||||
"registry": "https://registry.npmjs.org/"
|
"registry": "https://registry.npmjs.org/"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@testing-library/jest-dom": "5.16.5",
|
|
||||||
"@testing-library/react": "12.1.5",
|
|
||||||
"@testing-library/user-event": "14.4.3",
|
|
||||||
"@tryghost/content-api": "1.11.7",
|
"@tryghost/content-api": "1.11.7",
|
||||||
"flexsearch": "0.7.31",
|
"flexsearch": "0.7.31",
|
||||||
"react": "17.0.2",
|
"react": "17.0.2",
|
||||||
"react-dom": "17.0.2",
|
"react-dom": "17.0.2"
|
||||||
"react-scripts": "5.0.1"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "BROWSER=none react-scripts start",
|
"dev": "concurrently \"vite preview -l silent\" \"yarn build:watch\"",
|
||||||
"start:combined": "BROWSER=none node ./scripts/start-combined.js",
|
"build": "vite build",
|
||||||
"start:dev": "node ./scripts/start-mode.js",
|
"build:watch": "vite build --watch",
|
||||||
"dev": "node ./scripts/dev-mode.js",
|
"test": "vitest run",
|
||||||
"build": "npm run build:combined",
|
"test:ci": "yarn test --coverage",
|
||||||
"build:original": "react-scripts build",
|
"test:unit": "yarn test:ci",
|
||||||
"build:combined": "node ./scripts/build-combined.js",
|
|
||||||
"build:bundle": "webpack --config webpack.config.js",
|
|
||||||
"test:ui": "react-scripts test",
|
|
||||||
"test:unit": "yarn test",
|
|
||||||
"test": "yarn test:ui --watchAll=false --coverage",
|
|
||||||
"eject": "react-scripts eject",
|
|
||||||
"lint": "eslint src --ext .js --cache",
|
"lint": "eslint src --ext .js --cache",
|
||||||
"preship": "yarn lint",
|
"preship": "yarn lint",
|
||||||
"ship": "STATUS=$(git status --porcelain); echo $STATUS; if [ -z \"$STATUS\" ]; then yarn version; fi",
|
"ship": "STATUS=$(git status --porcelain); echo $STATUS; if [ -z \"$STATUS\" ]; then yarn version; fi",
|
||||||
"postship": "git push ${GHOST_UPSTREAM:-origin} --follow-tags && yarn publish . --tag $npm_package_version",
|
"postship": "git push ${GHOST_UPSTREAM:-origin} --follow-tags && npm publish",
|
||||||
"prepublishOnly": "yarn build"
|
"prepublishOnly": "yarn build"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
@ -75,19 +65,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"autoprefixer": "10.4.14",
|
"@vitejs/plugin-react": "4.0.3",
|
||||||
"chalk": "4.1.2",
|
"eslint-plugin-jest": "27.2.3",
|
||||||
"chokidar": "3.5.3",
|
"eslint-plugin-react": "7.33.0",
|
||||||
"copy-webpack-plugin": "11.0.0",
|
"vite": "4.4.7",
|
||||||
"minimist": "1.2.8",
|
"vite-plugin-svgr": "3.2.0",
|
||||||
"nock": "13.3.1",
|
"vitest": "0.33.0"
|
||||||
"postcss": "8.4.27",
|
|
||||||
"rewire": "6.0.0",
|
|
||||||
"serve-handler": "6.1.5",
|
|
||||||
"webpack-cli": "5.1.4"
|
|
||||||
},
|
|
||||||
"resolutions": {
|
|
||||||
"//": "See https://github.com/facebook/create-react-app/issues/11773",
|
|
||||||
"react-error-overlay": "6.0.11"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
plugins: {
|
|
||||||
autoprefixer: {}
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,27 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<meta name="theme-color" content="#000000" />
|
|
||||||
<meta
|
|
||||||
name="description"
|
|
||||||
content="Web site created using create-react-app"
|
|
||||||
/>
|
|
||||||
<title>React App</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
||||||
<div id="root"></div>
|
|
||||||
<!--
|
|
||||||
This HTML file is a template.
|
|
||||||
If you open it directly in the browser, you will see an empty page.
|
|
||||||
|
|
||||||
You can add webfonts, meta tags, or analytics to this file.
|
|
||||||
The build step will place the bundled scripts into the <body> tag.
|
|
||||||
|
|
||||||
To begin the development, run `npm start` or `yarn start`.
|
|
||||||
To create a production bundle, use `npm run build` or `yarn build`.
|
|
||||||
-->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,29 +0,0 @@
|
|||||||
const rewire = require('rewire');
|
|
||||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
||||||
const defaults = rewire('react-scripts/scripts/build.js');
|
|
||||||
let config = defaults.__get__('config');
|
|
||||||
|
|
||||||
config.optimization.splitChunks = {
|
|
||||||
cacheGroups: {
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
config.optimization.runtimeChunk = false;
|
|
||||||
|
|
||||||
// JS: Save built file in `/umd`
|
|
||||||
config.output.filename = '../umd/announcement-bar.min.js';
|
|
||||||
|
|
||||||
// CSS: Remove MiniCssPlugin from list of plugins
|
|
||||||
config.plugins = config.plugins.filter(plugin => !(plugin instanceof MiniCssExtractPlugin));
|
|
||||||
// CSS: replaces all MiniCssExtractPlugin.loader with style-loader to embed CSS in JS
|
|
||||||
config.module.rules[1].oneOf = config.module.rules[1].oneOf.map((rule) => {
|
|
||||||
if (!Object.prototype.hasOwnProperty.call(rule, 'use')) {
|
|
||||||
return rule;
|
|
||||||
}
|
|
||||||
return Object.assign({}, rule, {
|
|
||||||
use: rule.use.map(options => (/mini-css-extract-plugin/.test(options.loader)
|
|
||||||
? {loader: require.resolve('style-loader'), options: {}}
|
|
||||||
: options))
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,167 +0,0 @@
|
|||||||
const handler = require('serve-handler');
|
|
||||||
const http = require('http');
|
|
||||||
const chokidar = require('chokidar');
|
|
||||||
const chalk = require('chalk');
|
|
||||||
const {spawn} = require('child_process');
|
|
||||||
const minimist = require('minimist');
|
|
||||||
|
|
||||||
/* eslint-disable no-console */
|
|
||||||
const log = console.log;
|
|
||||||
/* eslint-enable no-console */
|
|
||||||
|
|
||||||
let buildProcess;
|
|
||||||
let fileChanges = [];
|
|
||||||
let spinner;
|
|
||||||
let stdOutChunks = [];
|
|
||||||
let stdErrChunks = [];
|
|
||||||
|
|
||||||
const {v, verbose, port = 5371, basic, b} = minimist(process.argv.slice(2));
|
|
||||||
const showVerbose = !!(v || verbose);
|
|
||||||
const showBasic = !!(b || basic);
|
|
||||||
|
|
||||||
function maybePluralize(count, noun, suffix = 's') {
|
|
||||||
return `${count} ${noun}${count !== 1 ? suffix : ''}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function printFileChanges() {
|
|
||||||
if (fileChanges.length > 0) {
|
|
||||||
const prefix = maybePluralize(fileChanges.length, 'file');
|
|
||||||
log(chalk.bold.hex('#ffa300').underline(`${prefix} changed`));
|
|
||||||
const message = fileChanges.map((path) => {
|
|
||||||
return chalk.hex('#ffa300').dim(`${path}`);
|
|
||||||
}).join('\n');
|
|
||||||
log(message);
|
|
||||||
log();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function printBuildSuccessDetails() {
|
|
||||||
if (showBasic) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((stdOutChunks && stdOutChunks.length > 0)) {
|
|
||||||
const detail = Buffer.concat(stdOutChunks.slice(4,7)).toString();
|
|
||||||
log();
|
|
||||||
log(chalk.dim(detail));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function printBuildErrorDetails() {
|
|
||||||
if ((stdOutChunks && stdOutChunks.length > 0)) {
|
|
||||||
const failDetails = Buffer.concat(stdOutChunks.slice(4, stdOutChunks.length - 1)).toString().replace(/^(?=\n)$|\s*$|\n\n+/gm, '');
|
|
||||||
log(chalk(failDetails));
|
|
||||||
}
|
|
||||||
if (stdErrChunks && stdErrChunks.length > 0) {
|
|
||||||
const stderrContent = Buffer.concat(stdErrChunks).toString();
|
|
||||||
log(chalk.dim(stderrContent));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function printBuildComplete(code) {
|
|
||||||
if (code === 0) {
|
|
||||||
if (!showVerbose) {
|
|
||||||
spinner && spinner.succeed(chalk.greenBright.bold('Build finished'));
|
|
||||||
printBuildSuccessDetails();
|
|
||||||
} else {
|
|
||||||
log();
|
|
||||||
log(chalk.bold.greenBright.bgBlackBright(`${'-'.repeat(25)}Build Success${'-'.repeat(25)}`));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!showVerbose) {
|
|
||||||
spinner && spinner.fail(chalk.redBright.bold('Build failed'));
|
|
||||||
printBuildErrorDetails();
|
|
||||||
} else {
|
|
||||||
log(chalk.bold.redBright.bgBlackBright(`${'-'.repeat(25)}Build finished: Failed${'-'.repeat(25)}`));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onBuildComplete(code) {
|
|
||||||
buildProcess = null;
|
|
||||||
printBuildComplete(code);
|
|
||||||
stdErrChunks = [];
|
|
||||||
stdOutChunks = [];
|
|
||||||
if (fileChanges.length > 0) {
|
|
||||||
buildPortal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBuildOptions() {
|
|
||||||
process.env.FORCE_COLOR = 'true';
|
|
||||||
const options = {
|
|
||||||
shell: true,
|
|
||||||
env: process.env
|
|
||||||
};
|
|
||||||
if (showVerbose) {
|
|
||||||
options.stdio = 'inherit';
|
|
||||||
}
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildPortal() {
|
|
||||||
if (buildProcess) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
printFileChanges();
|
|
||||||
fileChanges = [];
|
|
||||||
const options = getBuildOptions();
|
|
||||||
buildProcess = spawn('yarn build', options);
|
|
||||||
|
|
||||||
buildProcess.on('close', onBuildComplete);
|
|
||||||
|
|
||||||
if (!showVerbose) {
|
|
||||||
buildProcess.stdout.on('data', (data) => {
|
|
||||||
stdOutChunks.push(data);
|
|
||||||
});
|
|
||||||
buildProcess.stderr.on('data', (data) => {
|
|
||||||
stdErrChunks.push(data);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function watchFiles() {
|
|
||||||
const watcher = chokidar.watch('.', {
|
|
||||||
ignored: /build|node_modules|.git|public|umd|scripts|(^|[/])\../
|
|
||||||
});
|
|
||||||
|
|
||||||
watcher.on('ready', () => {
|
|
||||||
buildPortal();
|
|
||||||
}).on('change', (path) => {
|
|
||||||
if (!fileChanges.includes(path)) {
|
|
||||||
fileChanges.push(path);
|
|
||||||
}
|
|
||||||
if (!buildProcess) {
|
|
||||||
buildPortal();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function startDevServer() {
|
|
||||||
const server = http.createServer((request, response) => {
|
|
||||||
return handler(request, response, {
|
|
||||||
rewrites: [
|
|
||||||
{source: '/announcement-bar', destination: 'umd/announcement-bar.min.js'},
|
|
||||||
{source: '/announcement-bar.min.js.map', destination: 'umd/announcement-bar.min.js.map'}
|
|
||||||
],
|
|
||||||
headers: [
|
|
||||||
{
|
|
||||||
source: '**',
|
|
||||||
headers: [{
|
|
||||||
key: 'Cache-Control',
|
|
||||||
value: 'no-cache'
|
|
||||||
},{
|
|
||||||
key: 'Access-Control-Allow-Origin',
|
|
||||||
value: '*'
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
server.listen(port, () => {
|
|
||||||
watchFiles();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
startDevServer();
|
|
@ -1,8 +0,0 @@
|
|||||||
/** Script to load Portal bundle for local development */
|
|
||||||
function loadScript(src) {
|
|
||||||
var script = document.createElement('script');
|
|
||||||
script.src = src;
|
|
||||||
document.head.appendChild(script);
|
|
||||||
}
|
|
||||||
|
|
||||||
loadScript('http://localhost:3000/static/js/bundle.js');
|
|
@ -1,14 +0,0 @@
|
|||||||
const rewire = require('rewire');
|
|
||||||
const defaults = rewire('react-scripts/scripts/start.js');
|
|
||||||
let configFactory = defaults.__get__('configFactory');
|
|
||||||
|
|
||||||
defaults.__set__('configFactory', (env) => {
|
|
||||||
const config = configFactory(env);
|
|
||||||
config.optimization.splitChunks = {
|
|
||||||
cacheGroups: {
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
config.optimization.runtimeChunk = false;
|
|
||||||
return config;
|
|
||||||
});
|
|
@ -1,151 +0,0 @@
|
|||||||
const handler = require('serve-handler');
|
|
||||||
const http = require('http');
|
|
||||||
const chalk = require('chalk');
|
|
||||||
const {spawn} = require('child_process');
|
|
||||||
const minimist = require('minimist');
|
|
||||||
|
|
||||||
/* eslint-disable no-console */
|
|
||||||
const log = console.log;
|
|
||||||
/* eslint-enable no-console */
|
|
||||||
|
|
||||||
let yarnStartProcess;
|
|
||||||
let stdOutChunks = [];
|
|
||||||
let stdErrChunks = [];
|
|
||||||
let startYarnOutput = false;
|
|
||||||
|
|
||||||
const {v, verbose, port = 5370} = minimist(process.argv.slice(2));
|
|
||||||
const showVerbose = !!(v || verbose);
|
|
||||||
|
|
||||||
function clearConsole({withHistory = true} = {}) {
|
|
||||||
if (!withHistory) {
|
|
||||||
process.stdout.write('\x1Bc');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
process.stdout.write(
|
|
||||||
process.platform === 'win32' ? '\x1B[2J\x1B[0f' : '\x1B[2J\x1B[3J\x1B[H'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function printConfigInstruction() {
|
|
||||||
const data = {
|
|
||||||
announcementBar: {
|
|
||||||
url: `http://localhost:${port}/announcement-bar`
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const stringifedData = JSON.stringify(data, null, 2);
|
|
||||||
const splitData = stringifedData.split('\n');
|
|
||||||
log();
|
|
||||||
splitData.forEach((data, idx, arr) => {
|
|
||||||
if (idx === 0 || idx === arr.length - 1) {
|
|
||||||
log(chalk.grey(data));
|
|
||||||
} else {
|
|
||||||
log(chalk.bold.whiteBright(data));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
log();
|
|
||||||
}
|
|
||||||
|
|
||||||
function printInstructions() {
|
|
||||||
log();
|
|
||||||
log(chalk.yellowBright.underline(`Add announcementBar to your local Ghost config`));
|
|
||||||
printConfigInstruction();
|
|
||||||
log(chalk.cyanBright('='.repeat(50)));
|
|
||||||
log();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onProcessClose(code) {
|
|
||||||
yarnStartProcess = null;
|
|
||||||
stdErrChunks = [];
|
|
||||||
stdOutChunks = [];
|
|
||||||
log(chalk.redBright.bold.underline(`Please restart the script...\n`));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBuildOptions() {
|
|
||||||
process.env.FORCE_COLOR = 'true';
|
|
||||||
const options = {
|
|
||||||
shell: true,
|
|
||||||
env: process.env
|
|
||||||
};
|
|
||||||
if (showVerbose) {
|
|
||||||
options.stdio = 'inherit';
|
|
||||||
}
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
function doYarnStart() {
|
|
||||||
if (yarnStartProcess) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const options = getBuildOptions();
|
|
||||||
yarnStartProcess = spawn('yarn start:combined', options);
|
|
||||||
|
|
||||||
['SIGINT', 'SIGTERM'].forEach(function (sig) {
|
|
||||||
yarnStartProcess.on(sig, function () {
|
|
||||||
yarnStartProcess && yarnStartProcess.exit();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
yarnStartProcess.on('close', onProcessClose);
|
|
||||||
|
|
||||||
if (!showVerbose) {
|
|
||||||
yarnStartProcess.stdout.on('data', (data) => {
|
|
||||||
stdOutChunks.push(data);
|
|
||||||
printYarnProcessOutput(data);
|
|
||||||
});
|
|
||||||
yarnStartProcess.stderr.on('data', (data) => {
|
|
||||||
log(Buffer.from(data).toString());
|
|
||||||
stdErrChunks.push(data);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function printYarnProcessOutput(data) {
|
|
||||||
const dataStr = Buffer.from(data).toString();
|
|
||||||
const dataArr = dataStr.split('\n').filter((d) => {
|
|
||||||
return /\S/.test(d.trim());
|
|
||||||
});
|
|
||||||
if (dataArr.find(d => d.includes('Starting the development'))) {
|
|
||||||
startYarnOutput = true;
|
|
||||||
log(chalk.yellowBright('Starting the development server...\n'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dataArr.forEach((dataOut) => {
|
|
||||||
if (startYarnOutput) {
|
|
||||||
log(dataOut);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (startYarnOutput) {
|
|
||||||
log();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function startDevServer() {
|
|
||||||
const server = http.createServer((request, response) => {
|
|
||||||
return handler(request, response, {
|
|
||||||
rewrites: [
|
|
||||||
{source: '/announcement-bar', destination: 'scripts/load-portal.js'}
|
|
||||||
],
|
|
||||||
headers: [
|
|
||||||
{
|
|
||||||
source: '**',
|
|
||||||
headers: [{
|
|
||||||
key: 'Cache-Control',
|
|
||||||
value: 'no-cache'
|
|
||||||
},{
|
|
||||||
key: 'Access-Control-Allow-Origin',
|
|
||||||
value: '*'
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
server.listen(port, () => {
|
|
||||||
log(chalk.whiteBright(`Portal dev server is running on http://localhost:${port}`));
|
|
||||||
printInstructions();
|
|
||||||
doYarnStart();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
clearConsole({withHistory: false});
|
|
||||||
startDevServer();
|
|
@ -18,7 +18,6 @@ export function Main({apiUrl}) {
|
|||||||
|
|
||||||
getSiteSettings();
|
getSiteSettings();
|
||||||
// We only do this for init
|
// We only do this for init
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
import {fetch} from 'cross-fetch';
|
||||||
// allows you to do things like:
|
|
||||||
// expect(element).toHaveTextContent(/react/i)
|
// TODO: remove this once we're switched `jest` to `vi` in code
|
||||||
// learn more: https://github.com/testing-library/jest-dom
|
// eslint-disable-next-line no-undef
|
||||||
import '@testing-library/jest-dom';
|
globalThis.jest = vi;
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
globalThis.fetch = fetch;
|
||||||
|
@ -24,6 +24,6 @@ test('should call settings endpoint on init', () => {
|
|||||||
headers: {'Content-Type': 'application/json'},
|
headers: {'Content-Type': 'application/json'},
|
||||||
credentials: undefined,
|
credentials: undefined,
|
||||||
body: undefined
|
body: undefined
|
||||||
}),
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
65
apps/announcement-bar/vite.config.js
Normal file
65
apps/announcement-bar/vite.config.js
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import {resolve} from 'path';
|
||||||
|
import fs from 'fs/promises';
|
||||||
|
|
||||||
|
import {defineConfig} from 'vitest/config';
|
||||||
|
import reactPlugin from '@vitejs/plugin-react';
|
||||||
|
import svgrPlugin from 'vite-plugin-svgr';
|
||||||
|
|
||||||
|
import pkg from './package.json';
|
||||||
|
|
||||||
|
export default defineConfig((config) => {
|
||||||
|
const outputFileName = pkg.name[0] === '@' ? pkg.name.slice(pkg.name.indexOf('/') + 1) : pkg.name;
|
||||||
|
|
||||||
|
return {
|
||||||
|
clearScreen: false,
|
||||||
|
define: {
|
||||||
|
'process.env.NODE_ENV': JSON.stringify(config.mode)
|
||||||
|
},
|
||||||
|
preview: {
|
||||||
|
port: 4177
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
reactPlugin(),
|
||||||
|
svgrPlugin()
|
||||||
|
],
|
||||||
|
esbuild: {
|
||||||
|
loader: 'jsx',
|
||||||
|
include: /src\/.*\.jsx?$/,
|
||||||
|
exclude: []
|
||||||
|
},
|
||||||
|
optimizeDeps: {
|
||||||
|
esbuildOptions: {
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
name: 'load-js-files-as-jsx',
|
||||||
|
setup(build) {
|
||||||
|
build.onLoad({filter: /src\/.*\.js$/}, async args => ({
|
||||||
|
loader: 'jsx',
|
||||||
|
contents: await fs.readFile(args.path, 'utf8')
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
outDir: resolve(__dirname, 'umd'),
|
||||||
|
emptyOutDir: true,
|
||||||
|
minify: true,
|
||||||
|
sourcemap: true,
|
||||||
|
cssCodeSplit: true,
|
||||||
|
lib: {
|
||||||
|
entry: resolve(__dirname, 'src/index.js'),
|
||||||
|
formats: ['umd'],
|
||||||
|
name: pkg.name,
|
||||||
|
fileName: format => `${outputFileName}.min.js`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
test: {
|
||||||
|
globals: true,
|
||||||
|
environment: 'jsdom',
|
||||||
|
setupFiles: './src/setupTests.js',
|
||||||
|
testTimeout: 10000
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
@ -1,34 +0,0 @@
|
|||||||
const path = require('path');
|
|
||||||
const glob = require('glob');
|
|
||||||
const CopyPlugin = require('copy-webpack-plugin');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
mode: 'production',
|
|
||||||
entry: {
|
|
||||||
'bundle.js': glob.sync('build/static/?(js|css)/main.*.?(js|css)').map(f => path.resolve(__dirname, f))
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
filename: 'announcement-bar.min.js',
|
|
||||||
path: __dirname + '/umd'
|
|
||||||
},
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.css$/,
|
|
||||||
use: ['style-loader', 'css-loader']
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
new CopyPlugin({
|
|
||||||
patterns: [
|
|
||||||
{from: './build/static/js/main.js.map', to: './umd/announcement-bar.min.js.map'}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
],
|
|
||||||
performance: {
|
|
||||||
hints: false,
|
|
||||||
maxEntrypointSize: 560,
|
|
||||||
maxAssetSize: 5600
|
|
||||||
}
|
|
||||||
};
|
|
@ -55,8 +55,6 @@ Creates the production single minified bundle for external use in `umd/portal.mi
|
|||||||
### `yarn test`
|
### `yarn test`
|
||||||
|
|
||||||
Launches the test runner in the interactive watch mode.<br />
|
Launches the test runner in the interactive watch mode.<br />
|
||||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
|
||||||
|
|
||||||
|
|
||||||
## Publish
|
## Publish
|
||||||
|
|
||||||
@ -68,8 +66,3 @@ Run `yarn ship` to publish new version of script.
|
|||||||
- Publishes package on npm as `@tryghost/portal` and creates an unpkg link for script at https://unpkg.com/@tryghost/portal@VERSION
|
- Publishes package on npm as `@tryghost/portal` and creates an unpkg link for script at https://unpkg.com/@tryghost/portal@VERSION
|
||||||
|
|
||||||
(Core team only)
|
(Core team only)
|
||||||
|
|
||||||
## Learn More
|
|
||||||
|
|
||||||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
|
||||||
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
|
||||||
|
@ -73,7 +73,6 @@
|
|||||||
"@vitest/ui": "0.33.0",
|
"@vitest/ui": "0.33.0",
|
||||||
"concurrently": "8.2.0",
|
"concurrently": "8.2.0",
|
||||||
"cross-fetch": "4.0.0",
|
"cross-fetch": "4.0.0",
|
||||||
"eslint-config-react-app": "7.0.1",
|
|
||||||
"eslint-plugin-i18next": "6.0.3",
|
"eslint-plugin-i18next": "6.0.3",
|
||||||
"jsdom": "22.1.0",
|
"jsdom": "22.1.0",
|
||||||
"react": "17.0.2",
|
"react": "17.0.2",
|
||||||
|
@ -54,7 +54,6 @@
|
|||||||
"@vitejs/plugin-react": "4.0.3",
|
"@vitejs/plugin-react": "4.0.3",
|
||||||
"autoprefixer": "10.4.14",
|
"autoprefixer": "10.4.14",
|
||||||
"concurrently": "8.2.0",
|
"concurrently": "8.2.0",
|
||||||
"eslint-config-react-app": "7.0.1",
|
|
||||||
"eslint-plugin-react-hooks": "4.6.0",
|
"eslint-plugin-react-hooks": "4.6.0",
|
||||||
"eslint-plugin-react-refresh": "0.4.3",
|
"eslint-plugin-react-refresh": "0.4.3",
|
||||||
"eslint-plugin-tailwindcss": "3.13.0",
|
"eslint-plugin-tailwindcss": "3.13.0",
|
||||||
|
@ -1,77 +1,16 @@
|
|||||||
# Sodo Search
|
# Sodo Search
|
||||||
|
|
||||||
# Getting Started with Create React App
|
## Development
|
||||||
|
|
||||||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
### Pre-requisites
|
||||||
|
|
||||||
## Available Scripts
|
- Run `yarn` in Ghost monorepo root
|
||||||
|
- Run `yarn` in this directory
|
||||||
|
|
||||||
In the project directory, you can run:
|
### Running via Ghost `yarn dev` in root folder
|
||||||
|
|
||||||
### `yarn start`
|
|
||||||
|
|
||||||
Runs the app in the development mode.\
|
|
||||||
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
|
|
||||||
|
|
||||||
The page will reload when you make changes.\
|
|
||||||
You may also see any lint errors in the console.
|
|
||||||
|
|
||||||
### `yarn test`
|
|
||||||
|
|
||||||
Launches the test runner in the interactive watch mode.\
|
|
||||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
|
||||||
|
|
||||||
### `yarn build`
|
|
||||||
|
|
||||||
Builds the app for production to the `build` folder.\
|
|
||||||
It correctly bundles React in production mode and optimizes the build for the best performance.
|
|
||||||
|
|
||||||
The build is minified and the filenames include the hashes.\
|
|
||||||
Your app is ready to be deployed!
|
|
||||||
|
|
||||||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
|
||||||
|
|
||||||
### `yarn eject`
|
|
||||||
|
|
||||||
**Note: this is a one-way operation. Once you `eject`, you can't go back!**
|
|
||||||
|
|
||||||
If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
|
||||||
|
|
||||||
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
|
|
||||||
|
|
||||||
You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
|
|
||||||
|
|
||||||
## Learn More
|
|
||||||
|
|
||||||
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
|
||||||
|
|
||||||
To learn React, check out the [React documentation](https://reactjs.org/).
|
|
||||||
|
|
||||||
### Code Splitting
|
|
||||||
|
|
||||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
|
|
||||||
|
|
||||||
### Analyzing the Bundle Size
|
|
||||||
|
|
||||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
|
|
||||||
|
|
||||||
### Making a Progressive Web App
|
|
||||||
|
|
||||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
|
|
||||||
|
|
||||||
### Advanced Configuration
|
|
||||||
|
|
||||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
|
|
||||||
|
|
||||||
### Deployment
|
|
||||||
|
|
||||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
|
|
||||||
|
|
||||||
### `yarn build` fails to minify
|
|
||||||
|
|
||||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
|
|
||||||
|
|
||||||
|
You can automatically start the Sodo-Search dev server when developing Ghost by running Ghost (in root folder) via `yarn dev --search`.
|
||||||
|
|
||||||
# Copyright & License
|
# Copyright & License
|
||||||
|
|
||||||
Copyright (c) 2013-2022 Ghost Foundation - Released under the [MIT license](LICENSE).
|
Copyright (c) 2013-2022 Ghost Foundation - Released under the [MIT license](LICENSE).
|
||||||
|
@ -17,34 +17,24 @@
|
|||||||
"registry": "https://registry.npmjs.org/"
|
"registry": "https://registry.npmjs.org/"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@testing-library/jest-dom": "5.16.5",
|
|
||||||
"@testing-library/react": "12.1.5",
|
|
||||||
"@testing-library/user-event": "14.4.3",
|
|
||||||
"@tryghost/content-api": "1.11.7",
|
"@tryghost/content-api": "1.11.7",
|
||||||
"flexsearch": "0.7.31",
|
"flexsearch": "0.7.31",
|
||||||
"react": "17.0.2",
|
"react": "17.0.2",
|
||||||
"react-dom": "17.0.2",
|
"react-dom": "17.0.2"
|
||||||
"react-scripts": "5.0.1"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "BROWSER=none react-scripts start",
|
"dev": "concurrently \"vite preview -l silent\" \"yarn build:watch\" \"yarn tailwind\"",
|
||||||
"start:combined": "BROWSER=none node ./scripts/start-combined.js",
|
"build": "vite build && yarn tailwind:base",
|
||||||
"start:dev": "node ./scripts/start-mode.js",
|
"build:watch": "vite build --watch",
|
||||||
"tailwind": "yarn tailwind:base --watch ",
|
"tailwind": "yarn tailwind:base --watch ",
|
||||||
"tailwind:base": "npx tailwindcss -i ./src/index.css -o ./umd/main.css --minify",
|
"tailwind:base": "npx tailwindcss -i ./src/index.css -o ./umd/main.css --minify",
|
||||||
"dev": "concurrently \"node ./scripts/dev-mode.js\" \"yarn tailwind\"",
|
"test": "vitest run",
|
||||||
"build": "npm run build:combined && npm run tailwind:base",
|
"test:ci": "yarn test --coverage",
|
||||||
"build:original": "react-scripts build",
|
"test:unit": "yarn test:ci",
|
||||||
"build:combined": "node ./scripts/build-combined.js",
|
|
||||||
"build:bundle": "webpack --config webpack.config.js",
|
|
||||||
"test:ui": "react-scripts test",
|
|
||||||
"test:unit": "yarn test",
|
|
||||||
"test": "yarn test:ui --watchAll=false --coverage",
|
|
||||||
"eject": "react-scripts eject",
|
|
||||||
"lint": "eslint src --ext .js --cache",
|
"lint": "eslint src --ext .js --cache",
|
||||||
"preship": "yarn lint",
|
"preship": "yarn lint",
|
||||||
"ship": "STATUS=$(git status --porcelain); echo $STATUS; if [ -z \"$STATUS\" ]; then yarn version; fi",
|
"ship": "STATUS=$(git status --porcelain); echo $STATUS; if [ -z \"$STATUS\" ]; then yarn version; fi",
|
||||||
"postship": "git push ${GHOST_UPSTREAM:-origin} --follow-tags && yarn publish . --tag $npm_package_version",
|
"postship": "git push ${GHOST_UPSTREAM:-origin} --follow-tags && npm publish",
|
||||||
"prepublishOnly": "yarn build"
|
"prepublishOnly": "yarn build"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
@ -77,21 +67,12 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"autoprefixer": "10.4.14",
|
"@testing-library/jest-dom": "5.16.5",
|
||||||
"chalk": "4.1.2",
|
"@testing-library/react": "12.1.5",
|
||||||
"chokidar": "3.5.3",
|
"@vitejs/plugin-react": "4.0.3",
|
||||||
"copy-webpack-plugin": "11.0.0",
|
"nock": "13.1.2",
|
||||||
"minimist": "1.2.8",
|
"vite": "4.4.7",
|
||||||
"nock": "13.3.1",
|
"vite-plugin-svgr": "3.2.0",
|
||||||
"ora": "5.4.1",
|
"vitest": "0.33.0"
|
||||||
"postcss": "8.4.27",
|
|
||||||
"rewire": "6.0.0",
|
|
||||||
"serve-handler": "6.1.5",
|
|
||||||
"tailwindcss": "3.3.3",
|
|
||||||
"webpack-cli": "5.1.4"
|
|
||||||
},
|
|
||||||
"resolutions": {
|
|
||||||
"//": "See https://github.com/facebook/create-react-app/issues/11773",
|
|
||||||
"react-error-overlay": "6.0.11"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
plugins: {
|
|
||||||
tailwindcss: {},
|
|
||||||
autoprefixer: {},
|
|
||||||
},
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 3.8 KiB |
@ -1,43 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<meta name="theme-color" content="#000000" />
|
|
||||||
<meta
|
|
||||||
name="description"
|
|
||||||
content="Web site created using create-react-app"
|
|
||||||
/>
|
|
||||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
|
||||||
<!--
|
|
||||||
manifest.json provides metadata used when your web app is installed on a
|
|
||||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
|
||||||
-->
|
|
||||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
|
||||||
<!--
|
|
||||||
Notice the use of %PUBLIC_URL% in the tags above.
|
|
||||||
It will be replaced with the URL of the `public` folder during the build.
|
|
||||||
Only files inside the `public` folder can be referenced from the HTML.
|
|
||||||
|
|
||||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
|
||||||
work correctly both with client-side routing and a non-root public URL.
|
|
||||||
Learn how to configure a non-root public URL by running `npm run build`.
|
|
||||||
-->
|
|
||||||
<title>React App</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
||||||
<div id="root"></div>
|
|
||||||
<!--
|
|
||||||
This HTML file is a template.
|
|
||||||
If you open it directly in the browser, you will see an empty page.
|
|
||||||
|
|
||||||
You can add webfonts, meta tags, or analytics to this file.
|
|
||||||
The build step will place the bundled scripts into the <body> tag.
|
|
||||||
|
|
||||||
To begin the development, run `npm start` or `yarn start`.
|
|
||||||
To create a production bundle, use `npm run build` or `yarn build`.
|
|
||||||
-->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
Binary file not shown.
Before Width: | Height: | Size: 5.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 9.4 KiB |
@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"short_name": "React App",
|
|
||||||
"name": "Create React App Sample",
|
|
||||||
"icons": [
|
|
||||||
{
|
|
||||||
"src": "favicon.ico",
|
|
||||||
"sizes": "64x64 32x32 24x24 16x16",
|
|
||||||
"type": "image/x-icon"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "logo192.png",
|
|
||||||
"type": "image/png",
|
|
||||||
"sizes": "192x192"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "logo512.png",
|
|
||||||
"type": "image/png",
|
|
||||||
"sizes": "512x512"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"start_url": ".",
|
|
||||||
"display": "standalone",
|
|
||||||
"theme_color": "#000000",
|
|
||||||
"background_color": "#ffffff"
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
# https://www.robotstxt.org/robotstxt.html
|
|
||||||
User-agent: *
|
|
||||||
Disallow:
|
|
@ -1,29 +0,0 @@
|
|||||||
const rewire = require('rewire');
|
|
||||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
||||||
const defaults = rewire('react-scripts/scripts/build.js');
|
|
||||||
let config = defaults.__get__('config');
|
|
||||||
|
|
||||||
config.optimization.splitChunks = {
|
|
||||||
cacheGroups: {
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
config.optimization.runtimeChunk = false;
|
|
||||||
|
|
||||||
// JS: Save built file in `/umd`
|
|
||||||
config.output.filename = '../umd/sodo-search.min.js';
|
|
||||||
|
|
||||||
// CSS: Remove MiniCssPlugin from list of plugins
|
|
||||||
config.plugins = config.plugins.filter(plugin => !(plugin instanceof MiniCssExtractPlugin));
|
|
||||||
// CSS: replaces all MiniCssExtractPlugin.loader with style-loader to embed CSS in JS
|
|
||||||
config.module.rules[1].oneOf = config.module.rules[1].oneOf.map((rule) => {
|
|
||||||
if (!Object.prototype.hasOwnProperty.call(rule, 'use')) {
|
|
||||||
return rule;
|
|
||||||
}
|
|
||||||
return Object.assign({}, rule, {
|
|
||||||
use: rule.use.map(options => (/mini-css-extract-plugin/.test(options.loader)
|
|
||||||
? {loader: require.resolve('style-loader'), options: {}}
|
|
||||||
: options))
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,179 +0,0 @@
|
|||||||
const handler = require('serve-handler');
|
|
||||||
const http = require('http');
|
|
||||||
const chokidar = require('chokidar');
|
|
||||||
const chalk = require('chalk');
|
|
||||||
const {spawn} = require('child_process');
|
|
||||||
const minimist = require('minimist');
|
|
||||||
const ora = require('ora');
|
|
||||||
|
|
||||||
/* eslint-disable no-console */
|
|
||||||
const log = console.log;
|
|
||||||
/* eslint-enable no-console */
|
|
||||||
|
|
||||||
let buildProcess;
|
|
||||||
let fileChanges = [];
|
|
||||||
let spinner;
|
|
||||||
let stdOutChunks = [];
|
|
||||||
let stdErrChunks = [];
|
|
||||||
|
|
||||||
const {v, verbose, port = 5370, basic, b} = minimist(process.argv.slice(2));
|
|
||||||
const showVerbose = !!(v || verbose);
|
|
||||||
const showBasic = !!(b || basic);
|
|
||||||
|
|
||||||
function maybePluralize(count, noun, suffix = 's') {
|
|
||||||
return `${count} ${noun}${count !== 1 ? suffix : ''}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function printFileChanges() {
|
|
||||||
if (fileChanges.length > 0) {
|
|
||||||
const prefix = maybePluralize(fileChanges.length, 'file');
|
|
||||||
log(chalk.bold.hex('#ffa300').underline(`${prefix} changed`));
|
|
||||||
const message = fileChanges.map((path) => {
|
|
||||||
return chalk.hex('#ffa300').dim(`${path}`);
|
|
||||||
}).join('\n');
|
|
||||||
log(message);
|
|
||||||
log();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function printBuildSuccessDetails() {
|
|
||||||
if (showBasic) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((stdOutChunks && stdOutChunks.length > 0)) {
|
|
||||||
const detail = Buffer.concat(stdOutChunks.slice(4,7)).toString();
|
|
||||||
log();
|
|
||||||
log(chalk.dim(detail));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function printBuildErrorDetails() {
|
|
||||||
if ((stdOutChunks && stdOutChunks.length > 0)) {
|
|
||||||
const failDetails = Buffer.concat(stdOutChunks.slice(4, stdOutChunks.length - 1)).toString().replace(/^(?=\n)$|\s*$|\n\n+/gm, '');
|
|
||||||
log(chalk(failDetails));
|
|
||||||
}
|
|
||||||
if (stdErrChunks && stdErrChunks.length > 0) {
|
|
||||||
const stderrContent = Buffer.concat(stdErrChunks).toString();
|
|
||||||
log(chalk.dim(stderrContent));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function printBuildComplete(code) {
|
|
||||||
if (code === 0) {
|
|
||||||
if (!showVerbose) {
|
|
||||||
spinner && spinner.succeed(chalk.greenBright.bold('Build finished'));
|
|
||||||
printBuildSuccessDetails();
|
|
||||||
} else {
|
|
||||||
log();
|
|
||||||
log(chalk.bold.greenBright.bgBlackBright(`${'-'.repeat(25)}Build Success${'-'.repeat(25)}`));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!showVerbose) {
|
|
||||||
spinner && spinner.fail(chalk.redBright.bold('Build failed'));
|
|
||||||
printBuildErrorDetails();
|
|
||||||
} else {
|
|
||||||
log(chalk.bold.redBright.bgBlackBright(`${'-'.repeat(25)}Build finished: Failed${'-'.repeat(25)}`));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log();
|
|
||||||
}
|
|
||||||
|
|
||||||
function printBuildStart() {
|
|
||||||
if (showVerbose) {
|
|
||||||
log(chalk.bold.greenBright.bgBlackBright(`${'-'.repeat(32)}Building${'-'.repeat(32)}`));
|
|
||||||
log();
|
|
||||||
} else {
|
|
||||||
spinner = ora(chalk.magentaBright.bold('Bundling files, hang on...')).start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onBuildComplete(code) {
|
|
||||||
buildProcess = null;
|
|
||||||
printBuildComplete(code);
|
|
||||||
stdErrChunks = [];
|
|
||||||
stdOutChunks = [];
|
|
||||||
if (fileChanges.length > 0) {
|
|
||||||
buildPortal();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBuildOptions() {
|
|
||||||
process.env.FORCE_COLOR = 'true';
|
|
||||||
const options = {
|
|
||||||
shell: true,
|
|
||||||
env: process.env
|
|
||||||
};
|
|
||||||
if (showVerbose) {
|
|
||||||
options.stdio = 'inherit';
|
|
||||||
}
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildPortal() {
|
|
||||||
if (buildProcess) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
printFileChanges();
|
|
||||||
printBuildStart();
|
|
||||||
fileChanges = [];
|
|
||||||
const options = getBuildOptions();
|
|
||||||
buildProcess = spawn('yarn build', options);
|
|
||||||
|
|
||||||
buildProcess.on('close', onBuildComplete);
|
|
||||||
|
|
||||||
if (!showVerbose) {
|
|
||||||
buildProcess.stdout.on('data', (data) => {
|
|
||||||
stdOutChunks.push(data);
|
|
||||||
});
|
|
||||||
buildProcess.stderr.on('data', (data) => {
|
|
||||||
stdErrChunks.push(data);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function watchFiles() {
|
|
||||||
const watcher = chokidar.watch('.', {
|
|
||||||
ignored: /build|node_modules|.git|public|umd|scripts|(^|[/])\../
|
|
||||||
});
|
|
||||||
|
|
||||||
watcher.on('ready', () => {
|
|
||||||
buildPortal();
|
|
||||||
}).on('change', (path) => {
|
|
||||||
if (!fileChanges.includes(path)) {
|
|
||||||
fileChanges.push(path);
|
|
||||||
}
|
|
||||||
if (!buildProcess) {
|
|
||||||
buildPortal();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function startDevServer() {
|
|
||||||
const server = http.createServer((request, response) => {
|
|
||||||
return handler(request, response, {
|
|
||||||
rewrites: [
|
|
||||||
{source: '/sodo-search', destination: 'umd/sodo-search.min.js'},
|
|
||||||
{source: '/sodo-search.min.js.map', destination: 'umd/sodo-search.min.js.map'}
|
|
||||||
],
|
|
||||||
headers: [
|
|
||||||
{
|
|
||||||
source: '**',
|
|
||||||
headers: [{
|
|
||||||
key: 'Cache-Control',
|
|
||||||
value: 'no-cache'
|
|
||||||
},{
|
|
||||||
key: 'Access-Control-Allow-Origin',
|
|
||||||
value: '*'
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
server.listen(port, () => {
|
|
||||||
log(chalk.whiteBright(`Sodo-Search dev server is running on http://localhost:${port}`));
|
|
||||||
watchFiles();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
startDevServer();
|
|
@ -1,8 +0,0 @@
|
|||||||
/** Script to load Portal bundle for local development */
|
|
||||||
function loadScript(src) {
|
|
||||||
var script = document.createElement('script');
|
|
||||||
script.src = src;
|
|
||||||
document.head.appendChild(script);
|
|
||||||
}
|
|
||||||
|
|
||||||
loadScript('http://localhost:3000/static/js/bundle.js');
|
|
@ -1,14 +0,0 @@
|
|||||||
const rewire = require('rewire');
|
|
||||||
const defaults = rewire('react-scripts/scripts/start.js');
|
|
||||||
let configFactory = defaults.__get__('configFactory');
|
|
||||||
|
|
||||||
defaults.__set__('configFactory', (env) => {
|
|
||||||
const config = configFactory(env);
|
|
||||||
config.optimization.splitChunks = {
|
|
||||||
cacheGroups: {
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
config.optimization.runtimeChunk = false;
|
|
||||||
return config;
|
|
||||||
});
|
|
@ -1,181 +0,0 @@
|
|||||||
const handler = require('serve-handler');
|
|
||||||
const http = require('http');
|
|
||||||
const chalk = require('chalk');
|
|
||||||
const {spawn} = require('child_process');
|
|
||||||
const minimist = require('minimist');
|
|
||||||
|
|
||||||
/* eslint-disable no-console */
|
|
||||||
const log = console.log;
|
|
||||||
/* eslint-enable no-console */
|
|
||||||
|
|
||||||
let yarnStartProcess;
|
|
||||||
let tailwindServerProcess;
|
|
||||||
let stdOutChunks = [];
|
|
||||||
let stdErrChunks = [];
|
|
||||||
let startYarnOutput = false;
|
|
||||||
|
|
||||||
const {v, verbose, port = 5370} = minimist(process.argv.slice(2));
|
|
||||||
const showVerbose = !!(v || verbose);
|
|
||||||
|
|
||||||
function clearConsole({withHistory = true} = {}) {
|
|
||||||
if (!withHistory) {
|
|
||||||
process.stdout.write('\x1Bc');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
process.stdout.write(
|
|
||||||
process.platform === 'win32' ? '\x1B[2J\x1B[0f' : '\x1B[2J\x1B[3J\x1B[H'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function printConfigInstruction() {
|
|
||||||
const data = {
|
|
||||||
portal: {
|
|
||||||
url: `http://localhost:${port}/sodo-search`
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const stringifedData = JSON.stringify(data, null, 2);
|
|
||||||
const splitData = stringifedData.split('\n');
|
|
||||||
log();
|
|
||||||
splitData.forEach((data, idx, arr) => {
|
|
||||||
if (idx === 0 || idx === arr.length - 1) {
|
|
||||||
log(chalk.grey(data));
|
|
||||||
} else {
|
|
||||||
log(chalk.bold.whiteBright(data));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
log();
|
|
||||||
}
|
|
||||||
|
|
||||||
function printInstructions() {
|
|
||||||
log();
|
|
||||||
log(chalk.yellowBright.underline(`Add portal to your local Ghost config`));
|
|
||||||
printConfigInstruction();
|
|
||||||
log(chalk.cyanBright('='.repeat(50)));
|
|
||||||
log();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onProcessClose(code) {
|
|
||||||
yarnStartProcess = null;
|
|
||||||
tailwindServerProcess = null;
|
|
||||||
stdErrChunks = [];
|
|
||||||
stdOutChunks = [];
|
|
||||||
log(chalk.redBright.bold.underline(`Please restart the script...\n`));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getBuildOptions() {
|
|
||||||
process.env.FORCE_COLOR = 'true';
|
|
||||||
const options = {
|
|
||||||
shell: true,
|
|
||||||
env: process.env
|
|
||||||
};
|
|
||||||
if (showVerbose) {
|
|
||||||
options.stdio = 'inherit';
|
|
||||||
}
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
function doYarnStart() {
|
|
||||||
if (yarnStartProcess) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const options = getBuildOptions();
|
|
||||||
yarnStartProcess = spawn('yarn start:combined', options);
|
|
||||||
|
|
||||||
['SIGINT', 'SIGTERM'].forEach(function (sig) {
|
|
||||||
yarnStartProcess.on(sig, function () {
|
|
||||||
yarnStartProcess && yarnStartProcess.exit();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
yarnStartProcess.on('close', onProcessClose);
|
|
||||||
|
|
||||||
if (!showVerbose) {
|
|
||||||
yarnStartProcess.stdout.on('data', (data) => {
|
|
||||||
stdOutChunks.push(data);
|
|
||||||
printYarnProcessOutput(data);
|
|
||||||
});
|
|
||||||
yarnStartProcess.stderr.on('data', (data) => {
|
|
||||||
log(Buffer.from(data).toString());
|
|
||||||
stdErrChunks.push(data);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function doTailwindServerStart() {
|
|
||||||
if (tailwindServerProcess) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const options = getBuildOptions();
|
|
||||||
tailwindServerProcess = spawn('yarn tailwind', options);
|
|
||||||
|
|
||||||
['SIGINT', 'SIGTERM'].forEach(function (sig) {
|
|
||||||
tailwindServerProcess.on(sig, function () {
|
|
||||||
tailwindServerProcess && tailwindServerProcess.exit();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
tailwindServerProcess.on('close', onProcessClose);
|
|
||||||
|
|
||||||
if (!showVerbose) {
|
|
||||||
tailwindServerProcess.stdout.on('data', (data) => {
|
|
||||||
stdOutChunks.push(data);
|
|
||||||
printYarnProcessOutput(data);
|
|
||||||
});
|
|
||||||
tailwindServerProcess.stderr.on('data', (data) => {
|
|
||||||
log(Buffer.from(data).toString());
|
|
||||||
stdErrChunks.push(data);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function printYarnProcessOutput(data) {
|
|
||||||
const dataStr = Buffer.from(data).toString();
|
|
||||||
const dataArr = dataStr.split('\n').filter((d) => {
|
|
||||||
return /\S/.test(d.trim());
|
|
||||||
});
|
|
||||||
if (dataArr.find(d => d.includes('Starting the development'))) {
|
|
||||||
startYarnOutput = true;
|
|
||||||
log(chalk.yellowBright('Starting the development server...\n'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dataArr.forEach((dataOut) => {
|
|
||||||
if (startYarnOutput) {
|
|
||||||
log(dataOut);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (startYarnOutput) {
|
|
||||||
log();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function startDevServer() {
|
|
||||||
const server = http.createServer((request, response) => {
|
|
||||||
return handler(request, response, {
|
|
||||||
rewrites: [
|
|
||||||
{source: '/sodo-search', destination: 'scripts/load-portal.js'}
|
|
||||||
],
|
|
||||||
headers: [
|
|
||||||
{
|
|
||||||
source: '**',
|
|
||||||
headers: [{
|
|
||||||
key: 'Cache-Control',
|
|
||||||
value: 'no-cache'
|
|
||||||
},{
|
|
||||||
key: 'Access-Control-Allow-Origin',
|
|
||||||
value: '*'
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
server.listen(port, () => {
|
|
||||||
log(chalk.whiteBright(`Portal dev server is running on http://localhost:${port}`));
|
|
||||||
printInstructions();
|
|
||||||
doYarnStart();
|
|
||||||
doTailwindServerStart();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
clearConsole({withHistory: false});
|
|
||||||
startDevServer();
|
|
@ -1,10 +1,25 @@
|
|||||||
import {render} from '@testing-library/react';
|
import {render} from '@testing-library/react';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import nock from 'nock';
|
||||||
|
|
||||||
test('renders Sodo Search app component', () => {
|
test('renders Sodo Search app component', () => {
|
||||||
|
nock('http://localhost:3000/ghost/api/content')
|
||||||
|
.get('/posts/?key=69010382388f9de5869ad6e558&limit=10000&fields=id%2Cslug%2Ctitle%2Cexcerpt%2Curl%2Cupdated_at%2Cvisibility&order=updated_at%20DESC')
|
||||||
|
.reply(200, {
|
||||||
|
posts: []
|
||||||
|
})
|
||||||
|
.get('/authors/?key=69010382388f9de5869ad6e558&limit=10000&fields=id,slug,name,url,profile_image&order=updated_at%20DESC')
|
||||||
|
.reply(200, {
|
||||||
|
authors: []
|
||||||
|
})
|
||||||
|
.get('/tags/?key=69010382388f9de5869ad6e558&&limit=10000&fields=id,slug,name,url&order=updated_at%20DESC&filter=visibility%3Apublic')
|
||||||
|
.reply(200, {
|
||||||
|
tags: []
|
||||||
|
});
|
||||||
|
|
||||||
window.location.hash = '#/search';
|
window.location.hash = '#/search';
|
||||||
render(<App adminUrl="http://localhost" apiKey="69010382388f9de5869ad6e558" />);
|
render(<App adminUrl="http://localhost:3000" apiKey="69010382388f9de5869ad6e558" />);
|
||||||
// const containerElement = screen.getElementsByClassName('gh-portal-popup-container');
|
// const containerElement = screen.getElementsByClassName('gh-portal-popup-container');
|
||||||
// eslint-disable-next-line testing-library/no-node-access
|
// eslint-disable-next-line testing-library/no-node-access
|
||||||
const containerElement = document.querySelector('.gh-root-frame');
|
const containerElement = document.querySelector('.gh-root-frame');
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {Document} from 'flexsearch';
|
import Flexsearch from 'flexsearch';
|
||||||
import GhostContentAPI from '@tryghost/content-api';
|
import GhostContentAPI from '@tryghost/content-api';
|
||||||
|
|
||||||
export default class SearchIndex {
|
export default class SearchIndex {
|
||||||
@ -9,7 +9,7 @@ export default class SearchIndex {
|
|||||||
version: 'v5.0'
|
version: 'v5.0'
|
||||||
});
|
});
|
||||||
|
|
||||||
this.postsIndex = new Document({
|
this.postsIndex = new Flexsearch.Document({
|
||||||
tokenize: 'forward',
|
tokenize: 'forward',
|
||||||
document: {
|
document: {
|
||||||
id: 'id',
|
id: 'id',
|
||||||
@ -17,7 +17,7 @@ export default class SearchIndex {
|
|||||||
store: true
|
store: true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.authorsIndex = new Document({
|
this.authorsIndex = new Flexsearch.Document({
|
||||||
tokenize: 'forward',
|
tokenize: 'forward',
|
||||||
document: {
|
document: {
|
||||||
id: 'id',
|
id: 'id',
|
||||||
@ -25,7 +25,7 @@ export default class SearchIndex {
|
|||||||
store: true
|
store: true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.tagsIndex = new Document({
|
this.tagsIndex = new Flexsearch.Document({
|
||||||
tokenize: 'forward',
|
tokenize: 'forward',
|
||||||
document: {
|
document: {
|
||||||
id: 'id',
|
id: 'id',
|
||||||
|
@ -3,11 +3,11 @@ import nock from 'nock';
|
|||||||
|
|
||||||
describe('search index', function () {
|
describe('search index', function () {
|
||||||
test('initializes search index', async () => {
|
test('initializes search index', async () => {
|
||||||
const adminUrl = 'http://localhost';
|
const adminUrl = 'http://localhost:3000';
|
||||||
const apiKey = '69010382388f9de5869ad6e558';
|
const apiKey = '69010382388f9de5869ad6e558';
|
||||||
const searchIndex = new SearchIndex({adminUrl, apiKey, storage: localStorage});
|
const searchIndex = new SearchIndex({adminUrl, apiKey, storage: localStorage});
|
||||||
|
|
||||||
const scope = nock('http://localhost/ghost/api/content')
|
const scope = nock('http://localhost:3000/ghost/api/content')
|
||||||
.get('/posts/?key=69010382388f9de5869ad6e558&limit=10000&fields=id%2Cslug%2Ctitle%2Cexcerpt%2Curl%2Cupdated_at%2Cvisibility&order=updated_at%20DESC')
|
.get('/posts/?key=69010382388f9de5869ad6e558&limit=10000&fields=id%2Cslug%2Ctitle%2Cexcerpt%2Curl%2Cupdated_at%2Cvisibility&order=updated_at%20DESC')
|
||||||
.reply(200, {
|
.reply(200, {
|
||||||
posts: []
|
posts: []
|
||||||
@ -33,11 +33,11 @@ describe('search index', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('allows to search for indexed posts and authors', async () => {
|
test('allows to search for indexed posts and authors', async () => {
|
||||||
const adminUrl = 'http://localhost';
|
const adminUrl = 'http://localhost:3000';
|
||||||
const apiKey = '69010382388f9de5869ad6e558';
|
const apiKey = '69010382388f9de5869ad6e558';
|
||||||
const searchIndex = new SearchIndex({adminUrl, apiKey, storage: localStorage});
|
const searchIndex = new SearchIndex({adminUrl, apiKey, storage: localStorage});
|
||||||
|
|
||||||
nock('http://localhost/ghost/api/content')
|
nock('http://localhost:3000/ghost/api/content')
|
||||||
.get('/posts/?key=69010382388f9de5869ad6e558&limit=10000&fields=id%2Cslug%2Ctitle%2Cexcerpt%2Curl%2Cupdated_at%2Cvisibility&order=updated_at%20DESC')
|
.get('/posts/?key=69010382388f9de5869ad6e558&limit=10000&fields=id%2Cslug%2Ctitle%2Cexcerpt%2Curl%2Cupdated_at%2Cvisibility&order=updated_at%20DESC')
|
||||||
.reply(200, {
|
.reply(200, {
|
||||||
posts: [{
|
posts: [{
|
||||||
|
@ -1,5 +1,20 @@
|
|||||||
|
import {afterEach, expect} from 'vitest';
|
||||||
|
import {cleanup} from '@testing-library/react';
|
||||||
|
import {fetch} from 'cross-fetch';
|
||||||
|
import matchers from '@testing-library/jest-dom/matchers';
|
||||||
|
|
||||||
|
// TODO: remove this once we're switched `jest` to `vi` in code
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
globalThis.jest = vi;
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-undef
|
||||||
|
globalThis.fetch = fetch;
|
||||||
|
|
||||||
|
// Add the cleanup function for React testing library
|
||||||
|
afterEach(cleanup);
|
||||||
|
|
||||||
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
||||||
// allows you to do things like:
|
// allows you to do things like:
|
||||||
// expect(element).toHaveTextContent(/react/i)
|
// expect(element).toHaveTextContent(/react/i)
|
||||||
// learn more: https://github.com/testing-library/jest-dom
|
// learn more: https://github.com/testing-library/jest-dom
|
||||||
import '@testing-library/jest-dom';
|
expect.extend(matchers);
|
||||||
|
71
apps/sodo-search/vite.config.js
Normal file
71
apps/sodo-search/vite.config.js
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import {resolve} from 'path';
|
||||||
|
import fs from 'fs/promises';
|
||||||
|
|
||||||
|
import {defineConfig} from 'vitest/config';
|
||||||
|
import commonjs from 'vite-plugin-commonjs';
|
||||||
|
import reactPlugin from '@vitejs/plugin-react';
|
||||||
|
import svgrPlugin from 'vite-plugin-svgr';
|
||||||
|
|
||||||
|
import pkg from './package.json';
|
||||||
|
|
||||||
|
export default defineConfig((config) => {
|
||||||
|
const outputFileName = pkg.name[0] === '@' ? pkg.name.slice(pkg.name.indexOf('/') + 1) : pkg.name;
|
||||||
|
|
||||||
|
return {
|
||||||
|
clearScreen: false,
|
||||||
|
define: {
|
||||||
|
'process.env.NODE_ENV': JSON.stringify(config.mode)
|
||||||
|
},
|
||||||
|
preview: {
|
||||||
|
port: 4178
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
reactPlugin(),
|
||||||
|
svgrPlugin(),
|
||||||
|
commonjs({
|
||||||
|
dynamic: {
|
||||||
|
loose: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
],
|
||||||
|
esbuild: {
|
||||||
|
loader: 'jsx',
|
||||||
|
include: /src\/.*\.jsx?$/,
|
||||||
|
exclude: []
|
||||||
|
},
|
||||||
|
optimizeDeps: {
|
||||||
|
esbuildOptions: {
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
name: 'load-js-files-as-jsx',
|
||||||
|
setup(build) {
|
||||||
|
build.onLoad({filter: /src\/.*\.js$/}, async args => ({
|
||||||
|
loader: 'jsx',
|
||||||
|
contents: await fs.readFile(args.path, 'utf8')
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
outDir: resolve(__dirname, 'umd'),
|
||||||
|
emptyOutDir: true,
|
||||||
|
minify: true,
|
||||||
|
sourcemap: true,
|
||||||
|
cssCodeSplit: true,
|
||||||
|
lib: {
|
||||||
|
entry: resolve(__dirname, 'src/index.js'),
|
||||||
|
formats: ['umd'],
|
||||||
|
name: pkg.name,
|
||||||
|
fileName: format => `${outputFileName}.min.js`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
test: {
|
||||||
|
globals: true,
|
||||||
|
environment: 'jsdom',
|
||||||
|
setupFiles: './src/setupTests.js',
|
||||||
|
testTimeout: 10000
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
@ -1,34 +0,0 @@
|
|||||||
const path = require('path');
|
|
||||||
const glob = require('glob');
|
|
||||||
const CopyPlugin = require('copy-webpack-plugin');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
mode: 'production',
|
|
||||||
entry: {
|
|
||||||
'bundle.js': glob.sync('build/static/?(js|css)/main.*.?(js|css)').map(f => path.resolve(__dirname, f))
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
filename: 'sodo-search.min.js',
|
|
||||||
path: __dirname + '/umd'
|
|
||||||
},
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.css$/,
|
|
||||||
use: ['style-loader', 'css-loader']
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
new CopyPlugin({
|
|
||||||
patterns: [
|
|
||||||
{from: './build/static/js/main.js.map', to: './umd/sodo-search.min.js.map'}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
],
|
|
||||||
performance: {
|
|
||||||
hints: false,
|
|
||||||
maxEntrypointSize: 560,
|
|
||||||
maxAssetSize: 5600
|
|
||||||
}
|
|
||||||
};
|
|
@ -122,6 +122,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"concurrently": "8.2.0",
|
"concurrently": "8.2.0",
|
||||||
"eslint": "8.44.0",
|
"eslint": "8.44.0",
|
||||||
|
"eslint-config-react-app": "7.0.1",
|
||||||
"eslint-plugin-ghost": "3.3.0",
|
"eslint-plugin-ghost": "3.3.0",
|
||||||
"husky": "8.0.3",
|
"husky": "8.0.3",
|
||||||
"lint-staged": "13.2.3",
|
"lint-staged": "13.2.3",
|
||||||
|
Loading…
Reference in New Issue
Block a user