mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-05-17 05:19:39 +03:00
add v2 docs project
This commit is contained in:
+24
-5
@@ -38,11 +38,21 @@ const defaultRules = {
|
||||
],
|
||||
},
|
||||
],
|
||||
'react/function-component-definition': [
|
||||
'error',
|
||||
{
|
||||
namedComponents: 'arrow-function',
|
||||
unnamedComponents: 'arrow-function',
|
||||
},
|
||||
],
|
||||
'react/jsx-filename-extension': ['error', { extensions: ['.jsx', '.tsx'] }],
|
||||
};
|
||||
const defaultExtends = ['airbnb', 'prettier', 'plugin:react/jsx-runtime'];
|
||||
const defaultPlugins = ['prettier', 'json', '@typescript-eslint', 'import', 'react'];
|
||||
|
||||
module.exports = {
|
||||
extends: ['airbnb', 'prettier'],
|
||||
plugins: ['prettier', 'json', '@typescript-eslint', 'import'],
|
||||
extends: defaultExtends,
|
||||
plugins: defaultPlugins,
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
@@ -64,7 +74,11 @@ module.exports = {
|
||||
'import/resolver': {
|
||||
typescript: {
|
||||
alwaysTryTypes: true,
|
||||
project: ['./packages/**/tsconfig.json', './local/**/tsconfig.json'],
|
||||
project: [
|
||||
'./packages/**/tsconfig.json',
|
||||
'./docs/**/tsconfig.json',
|
||||
'./local/**/tsconfig.json',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -72,11 +86,16 @@ module.exports = {
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.ts', '*.tsx', '*.d.ts'],
|
||||
extends: ['plugin:@typescript-eslint/recommended', 'airbnb', 'prettier'],
|
||||
extends: [...defaultExtends, 'plugin:@typescript-eslint/recommended'],
|
||||
plugins: defaultPlugins,
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: ['./packages/**/tsconfig.json', './local/**/tsconfig.json'],
|
||||
project: [
|
||||
'./packages/**/tsconfig.json',
|
||||
'./docs/**/tsconfig.json',
|
||||
'./local/**/tsconfig.json',
|
||||
],
|
||||
},
|
||||
rules: {
|
||||
...defaultRules,
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
**/.next/
|
||||
**/next-app/out/
|
||||
**/next-app/src/
|
||||
**/next-app/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"printWidth": 100,
|
||||
"tabWidth": 2,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "es5",
|
||||
"jsxBracketSameLine": true,
|
||||
"arrowParens": "always",
|
||||
"endOfLine": "lf",
|
||||
"parser": "babel-ts",
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.html",
|
||||
"options": { "parser": "html" }
|
||||
},
|
||||
{
|
||||
"files": "*.css",
|
||||
"options": { "parser": "css" }
|
||||
},
|
||||
{
|
||||
"files": "*.scss",
|
||||
"options": { "parser": "scss" }
|
||||
},
|
||||
{
|
||||
"files": ".prettierrc",
|
||||
"options": { "parser": "json" }
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
||||
|
||||
## Getting Started
|
||||
|
||||
First, run the development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
# or
|
||||
yarn dev
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
|
||||
You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.
|
||||
|
||||
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
|
||||
|
||||
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
|
||||
|
||||
## Learn More
|
||||
|
||||
To learn more about Next.js, take a look at the following resources:
|
||||
|
||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||
|
||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
|
||||
|
||||
## Deploy on Vercel
|
||||
|
||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||
|
||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|
||||
@@ -0,0 +1,47 @@
|
||||
import glob from 'fast-glob';
|
||||
import { esbuild } from '@~local-docs/esbuild';
|
||||
|
||||
const processArgs = process.argv.slice(2);
|
||||
const watch = processArgs.includes('-w');
|
||||
const minify = processArgs.includes('-p');
|
||||
const define = {};
|
||||
|
||||
await esbuild({
|
||||
entryPoints: glob.sync('./src/**/*.{ts,tsx,js,jsx}'),
|
||||
outdir: './next-app/src',
|
||||
outbase: 'src',
|
||||
platform: 'node',
|
||||
loader: {
|
||||
'.aac': 'copy',
|
||||
'.avif': 'copy',
|
||||
'.css': 'copy',
|
||||
'.eot': 'copy',
|
||||
'.flac': 'copy',
|
||||
'.gif': 'copy',
|
||||
'.gql': 'text',
|
||||
'.graphql': 'text',
|
||||
'.ico': 'copy',
|
||||
'.jpeg': 'copy',
|
||||
'.jpg': 'copy',
|
||||
'.md': 'jsx',
|
||||
'.mdx': 'jsx',
|
||||
'.mp3': 'copy',
|
||||
'.mp4': 'copy',
|
||||
'.ogg': 'copy',
|
||||
'.otf': 'copy',
|
||||
'.png': 'copy',
|
||||
'.sql': 'text',
|
||||
'.svg': 'copy',
|
||||
'.ttf': 'copy',
|
||||
'.wav': 'copy',
|
||||
'.webm': 'copy',
|
||||
'.webmanifest': 'copy',
|
||||
'.webp': 'copy',
|
||||
'.woff': 'copy',
|
||||
'.woff2': 'copy',
|
||||
'.zip': 'copy',
|
||||
},
|
||||
minify,
|
||||
define,
|
||||
watch,
|
||||
});
|
||||
Vendored
+120
@@ -0,0 +1,120 @@
|
||||
declare module '*.ico' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.aac' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.avif' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.css' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.eot' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.flac' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.gif' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.gql' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.graphql' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.jpeg' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.jpg' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.md' {
|
||||
import type { ComponentType as MdComponentType } from 'react';
|
||||
|
||||
export const attributes: any;
|
||||
export const filename: string;
|
||||
const Component: MdComponentType;
|
||||
export default Component;
|
||||
}
|
||||
declare module '*.mdx' {
|
||||
import type { ComponentType as MdxComponentType } from 'react';
|
||||
|
||||
export const attributes: any;
|
||||
export const filename: string;
|
||||
const Component: MdxComponentType;
|
||||
export default Component;
|
||||
}
|
||||
declare module '*.mp3' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.mp4' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.ogg' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.otf' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.png' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.sql' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.svg' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.ttf' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.wav' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.webm' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.webp' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.woff' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.woff2' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.webmanifest' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
declare module '*.zip' {
|
||||
const asset: string;
|
||||
export default asset;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"sideEffects": false,
|
||||
"main": "src/esbuild.js",
|
||||
"type": "module"
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import esbuildOriginal from 'esbuild';
|
||||
import { writeOnlyChanges } from './writeOnlyChanges.js';
|
||||
import { esbuildClearOldBuild } from './plugins/clearOldBuild.js';
|
||||
import { esbuildPluginStyles } from './plugins/styles.js';
|
||||
import { esbuildPluginTailwind } from './plugins/tailwind.js';
|
||||
import { esbuildPluginExternal } from './plugins/external.js';
|
||||
|
||||
const changesMap = new Map();
|
||||
const writeBuild = async (build) => {
|
||||
if (build?.outputFiles) {
|
||||
await writeOnlyChanges(build.outputFiles, changesMap);
|
||||
}
|
||||
};
|
||||
|
||||
export const esbuild = async (options = {}, { tailwindConfig = './tailwind.config.js' } = {}) => {
|
||||
const buildOptions = {
|
||||
bundle: true,
|
||||
splitting: true,
|
||||
allowOverwrite: true,
|
||||
incremental: true,
|
||||
metafile: true,
|
||||
write: false,
|
||||
format: 'esm',
|
||||
platform: 'node',
|
||||
chunkNames: 'chunks/[name]-[hash]',
|
||||
assetNames: 'assets/[dir]/[name]',
|
||||
entryNames: '[dir]/[name]',
|
||||
jsx: 'automatic',
|
||||
...options,
|
||||
external: [...(options.external || [])],
|
||||
watch: options.watch && {
|
||||
async onRebuild(_, rebuildResult) {
|
||||
await writeBuild(rebuildResult);
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
esbuildClearOldBuild(),
|
||||
esbuildPluginStyles({
|
||||
sassFilesRegex: /\.s[ac]ss$/,
|
||||
cssFilesRegex: /\.css$/,
|
||||
cssModulesRegex: /\.module\.\S+$/,
|
||||
}),
|
||||
esbuildPluginTailwind({
|
||||
tailwindConfig,
|
||||
tailwindCssFileRegex: /tailwind.*\.css$/,
|
||||
}),
|
||||
esbuildPluginExternal(),
|
||||
...(options.plugins || []),
|
||||
],
|
||||
};
|
||||
const build = await esbuildOriginal.build(buildOptions);
|
||||
await writeBuild(build);
|
||||
return build;
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
export const esbuildClearOldBuild = () => {
|
||||
let cleared = false;
|
||||
return {
|
||||
name: 'clearOldBuild',
|
||||
setup(build) {
|
||||
const initBuildOptions = build.initialOptions;
|
||||
|
||||
build.onStart(() => {
|
||||
if (!cleared && initBuildOptions.outdir) {
|
||||
fs.rmSync(path.resolve(initBuildOptions.outdir), { recursive: true, force: true });
|
||||
cleared = true;
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
const externalRegex = /node_modules/;
|
||||
|
||||
export const esbuildPluginExternal = () => ({
|
||||
name: 'external',
|
||||
setup(build) {
|
||||
build.onResolve({ filter: /.*/, namespace: 'file' }, async (args) => {
|
||||
const { resolveDir, kind } = args;
|
||||
|
||||
if (kind !== 'entry-point') {
|
||||
const { path: resolvedPath } = await build.resolve(args.path, {
|
||||
resolveDir,
|
||||
kind,
|
||||
namespace: 'resolve-pls',
|
||||
});
|
||||
|
||||
if (externalRegex.test(resolvedPath)) {
|
||||
return {
|
||||
path: args.path,
|
||||
external: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,243 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import crypto from 'node:crypto';
|
||||
import sass from 'sass';
|
||||
import esbuild from 'esbuild';
|
||||
import { writeOnlyChanges } from '../writeOnlyChanges.js';
|
||||
|
||||
const externalRegex = /node_modules/;
|
||||
const isExtendedLengthPath = /^\\\\\?\\/;
|
||||
|
||||
const normalizePathSlashes = (pathToNormalize) =>
|
||||
isExtendedLengthPath.test(pathToNormalize)
|
||||
? pathToNormalize
|
||||
: pathToNormalize.replace(/\\/g, '/');
|
||||
|
||||
const getHash = (content) => crypto.createHash('sha1').update(content).digest('hex');
|
||||
|
||||
export const esbuildPluginStyles = (options) => {
|
||||
const changesMap = new Map();
|
||||
const {
|
||||
cssBuildOptions = {},
|
||||
cssModulesRegex = /\.module\.\S+$/,
|
||||
sassFilesRegex = /\.s[ac]ss$/,
|
||||
cssFilesRegex = /\.css$/,
|
||||
} = options;
|
||||
const sassCache = new Map();
|
||||
const esbuildCache = new Map();
|
||||
|
||||
const replaceExtension = (filePath, replacement = '') => {
|
||||
const replacementRegex = /\.[^.]*$/;
|
||||
return filePath.replace(
|
||||
replacementRegex,
|
||||
typeof replacement === 'function'
|
||||
? replacement((filePath.match(replacementRegex) || [])[0] || '')
|
||||
: replacement
|
||||
);
|
||||
};
|
||||
|
||||
const resolveFile = async (build, onResolveArgs) => {
|
||||
const { resolveDir, importer } = onResolveArgs;
|
||||
const { path: resolvedPath } = await build.resolve(onResolveArgs.path, {
|
||||
resolveDir,
|
||||
importer,
|
||||
kind: 'entry-point',
|
||||
namespace: 'resolve-pls',
|
||||
});
|
||||
const external = externalRegex.test(resolvedPath);
|
||||
|
||||
return [resolvedPath, external];
|
||||
};
|
||||
|
||||
const resolveProcessedCss = (args) => ({
|
||||
path: args.path,
|
||||
namespace: 'css-processed',
|
||||
pluginData: args.pluginData,
|
||||
});
|
||||
|
||||
const setupSassResolve = (build) => {
|
||||
build.onResolve({ filter: sassFilesRegex, namespace: 'file' }, async (args) => {
|
||||
const [resolvedPath, external] = await resolveFile(build, args);
|
||||
|
||||
return external
|
||||
? {
|
||||
path: args.path,
|
||||
external: true,
|
||||
}
|
||||
: {
|
||||
path: cssModulesRegex.test(resolvedPath)
|
||||
? `${resolvedPath}.module.css`
|
||||
: `${resolvedPath}.css`,
|
||||
namespace: 'sass',
|
||||
pluginData: {
|
||||
resolvedPath,
|
||||
},
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const setupCssResolve = (build) => {
|
||||
build.onResolve({ filter: cssFilesRegex, namespace: 'file' }, async (args) => {
|
||||
const [resolvedPath, external] = await resolveFile(build, args);
|
||||
|
||||
return external
|
||||
? {
|
||||
path: args.path,
|
||||
external: true,
|
||||
}
|
||||
: {
|
||||
path: resolvedPath,
|
||||
namespace: 'css',
|
||||
pluginData: {
|
||||
resolvedPath,
|
||||
},
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const transpileSass = (css, filePath) => {
|
||||
const currHash = getHash(css);
|
||||
const [cacheHash] = sassCache.get(filePath) || [];
|
||||
|
||||
if (currHash !== cacheHash) {
|
||||
try {
|
||||
const result = sass.compile(filePath);
|
||||
sassCache.set(filePath, [currHash, result.css]);
|
||||
} catch {}
|
||||
}
|
||||
|
||||
return sassCache.get(filePath)[1] || css;
|
||||
};
|
||||
|
||||
const esbuildCss = async (initialBuildOptions, stdin, filePath) => {
|
||||
const source = stdin.contents;
|
||||
const currHash = getHash(source);
|
||||
const [cacheHash] = esbuildCache.get(filePath) || [];
|
||||
|
||||
if (currHash !== cacheHash) {
|
||||
const finalCssBuildOptions =
|
||||
typeof cssBuildOptions === 'function'
|
||||
? cssBuildOptions(initialBuildOptions)
|
||||
: cssBuildOptions;
|
||||
const { assetNames } = initialBuildOptions;
|
||||
const { outputFiles, metafile, errors, warnings } = await esbuild.build({
|
||||
...initialBuildOptions,
|
||||
stdin,
|
||||
write: false,
|
||||
bundle: true,
|
||||
metafile: true,
|
||||
entryNames: assetNames,
|
||||
entryPoints: [],
|
||||
plugins: [],
|
||||
...finalCssBuildOptions,
|
||||
});
|
||||
|
||||
if (errors?.length) {
|
||||
return {
|
||||
errors,
|
||||
};
|
||||
}
|
||||
|
||||
const { outputs } = metafile;
|
||||
const watchFiles = Object.values(outputs).reduce((arr, { inputs }) => {
|
||||
arr.push(...Object.keys(inputs).map((input) => path.resolve(input)));
|
||||
return arr;
|
||||
}, []);
|
||||
const entry = Object.keys(outputs).find((out) => outputs[out].entryPoint);
|
||||
const entryFile = outputFiles.find((file) =>
|
||||
normalizePathSlashes(file.path).endsWith(normalizePathSlashes(entry))
|
||||
);
|
||||
|
||||
const result = {
|
||||
outputFiles,
|
||||
entryFile,
|
||||
watchFiles,
|
||||
warnings,
|
||||
};
|
||||
|
||||
esbuildCache.set(filePath, [currHash, result]);
|
||||
}
|
||||
|
||||
return esbuildCache.get(filePath)[1];
|
||||
};
|
||||
|
||||
return {
|
||||
name: 'esbuild-plugin-styles',
|
||||
|
||||
async setup(build) {
|
||||
const initBuildOptions = build.initialOptions;
|
||||
|
||||
setupSassResolve(build);
|
||||
setupCssResolve(build);
|
||||
|
||||
// move newly crete stub modules to 'css-processed' namespace
|
||||
build.onResolve({ filter: cssFilesRegex, namespace: 'sass' }, resolveProcessedCss);
|
||||
build.onResolve({ filter: cssFilesRegex, namespace: 'css' }, resolveProcessedCss);
|
||||
|
||||
// resolve asset imports for generated css files
|
||||
build.onResolve({ filter: /.*/, namespace: 'css-processed' }, async (args) =>
|
||||
// since we don't consume them its fine that the imports are wrong
|
||||
({
|
||||
path: args.path,
|
||||
external: true,
|
||||
})
|
||||
);
|
||||
|
||||
build.onLoad({ filter: cssFilesRegex }, async (args) => {
|
||||
const { namespace, pluginData } = args;
|
||||
|
||||
if (namespace === 'css-processed') {
|
||||
const { contents } = pluginData;
|
||||
return {
|
||||
contents,
|
||||
loader: 'copy',
|
||||
resolveDir: path.dirname(args.path),
|
||||
};
|
||||
}
|
||||
|
||||
const { resolvedPath } = pluginData;
|
||||
const fileName = path.basename(resolvedPath);
|
||||
const resolveDir = path.dirname(resolvedPath);
|
||||
const css = await fs.promises.readFile(resolvedPath);
|
||||
const source = namespace === 'sass' ? transpileSass(css, resolvedPath) : css;
|
||||
|
||||
const { outputFiles, entryFile, watchFiles, warnings, errors } = await esbuildCss(
|
||||
initBuildOptions,
|
||||
{
|
||||
contents: source,
|
||||
sourcefile: fileName,
|
||||
resolveDir,
|
||||
loader: 'css',
|
||||
},
|
||||
resolvedPath
|
||||
);
|
||||
|
||||
if (errors) {
|
||||
return {
|
||||
errors,
|
||||
};
|
||||
}
|
||||
|
||||
const entryFilePath = path.resolve(
|
||||
path.dirname(entryFile.path),
|
||||
`${path.basename(replaceExtension(args.path))}${path
|
||||
.basename(entryFile.path)
|
||||
.replace('stdin', '')}`
|
||||
);
|
||||
const adaptedOutputFiles = outputFiles.filter((file) => file !== entryFile);
|
||||
|
||||
await writeOnlyChanges(adaptedOutputFiles, changesMap);
|
||||
|
||||
return {
|
||||
contents: `export { default } from ${JSON.stringify(entryFilePath)};`,
|
||||
resolveDir,
|
||||
watchFiles,
|
||||
warnings,
|
||||
pluginData: {
|
||||
contents: entryFile.contents,
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
import path from 'node:path';
|
||||
import minimatch from 'minimatch';
|
||||
import postcss from 'postcss';
|
||||
import tailwindcss from 'tailwindcss';
|
||||
|
||||
import { resolveConfig } from '../resolveConfig.js';
|
||||
|
||||
export const esbuildPluginTailwind = ({
|
||||
tailwindCssFileRegex = /tailwind.*\.css$/,
|
||||
tailwindConfig = './tailwind.config.js',
|
||||
} = {}) => ({
|
||||
name: 'tailwind',
|
||||
async setup(build) {
|
||||
const resolvedTailwindConfig = await resolveConfig(tailwindConfig);
|
||||
|
||||
build.onEnd(async (result) => {
|
||||
if (result) {
|
||||
const { metafile, outputFiles } = result;
|
||||
const { inputs } = metafile;
|
||||
const tailwindFile = outputFiles.find(({ path: outputFilePath }) =>
|
||||
tailwindCssFileRegex.test(outputFilePath)
|
||||
);
|
||||
|
||||
if (tailwindFile) {
|
||||
const { path: tailwindFilePath, text: tailwindFileCss } = tailwindFile;
|
||||
const tailwindContentGlobs = (resolvedTailwindConfig?.content || []).filter(
|
||||
(entry) => typeof entry === 'string'
|
||||
);
|
||||
const inputFilePaths = Object.keys(inputs).map((input) => path.resolve(input));
|
||||
const includedFiles = Array.from(
|
||||
new Set(
|
||||
tailwindContentGlobs
|
||||
.map((glob) => minimatch.match(inputFilePaths, glob, { dot: true }))
|
||||
.flat()
|
||||
)
|
||||
);
|
||||
|
||||
const postcssResult = await postcss([
|
||||
tailwindcss({ ...(resolvedTailwindConfig || {}), content: includedFiles }),
|
||||
]).process(tailwindFileCss, {
|
||||
from: tailwindFilePath,
|
||||
});
|
||||
|
||||
tailwindFile.contents = Buffer.from(postcssResult.css);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
import url from 'node:url';
|
||||
import path from 'node:path';
|
||||
|
||||
export const resolveConfig = async (configPath) => {
|
||||
if (configPath) {
|
||||
const loadedConfig = (
|
||||
await import(url.pathToFileURL(path.resolve(configPath))).catch(() => ({}))
|
||||
).default;
|
||||
if (loadedConfig) {
|
||||
return loadedConfig;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
import fs from 'node:fs';
|
||||
import crypto from 'node:crypto';
|
||||
import path from 'node:path';
|
||||
|
||||
const getHash = (content) => crypto.createHash('md5').update(content).digest('hex');
|
||||
|
||||
export const writeOnlyChanges = async (outputFiles, changesMap) => {
|
||||
await Promise.all(
|
||||
outputFiles.map(({ path: filepath }) =>
|
||||
fs.promises.mkdir(path.dirname(filepath), { recursive: true })
|
||||
)
|
||||
);
|
||||
await Promise.all(
|
||||
outputFiles.map(({ path: filepath, contents }) => {
|
||||
const currContentsHash = getHash(contents);
|
||||
const cacheHash = changesMap.get(filepath);
|
||||
|
||||
if (cacheHash !== currContentsHash) {
|
||||
changesMap.set(filepath, currContentsHash);
|
||||
return fs.promises.writeFile(filepath, contents);
|
||||
}
|
||||
return null;
|
||||
})
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"private": true,
|
||||
"main": "tailwind.config.js"
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
const defaultTheme = require('tailwindcss/defaultTheme');
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
theme: {
|
||||
extend: {},
|
||||
container: {
|
||||
center: true,
|
||||
},
|
||||
fontFamily: {
|
||||
sans: ['Noto Sans', ...defaultTheme.fontFamily.sans],
|
||||
},
|
||||
fontWeight: {
|
||||
normal: 400,
|
||||
medium: 600,
|
||||
bold: 800,
|
||||
},
|
||||
screens: {
|
||||
xxs: '374px',
|
||||
xs: '640px',
|
||||
sm: '768px',
|
||||
md: '960px',
|
||||
lg: '1280px',
|
||||
xl: '1440px',
|
||||
xxl: '1536px',
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
reactStrictMode: true,
|
||||
swcMinify: true,
|
||||
images: {
|
||||
unoptimized: true,
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = nextConfig;
|
||||
Generated
+7418
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "concurrently \"node esbuild.mjs -w\" \"wait-on -d 2000 ./next-app/src && cd next-app && next dev\"",
|
||||
"build": "node esbuild.mjs && cd next-app && next build && next export",
|
||||
"start": "node esbuild.mjs && cd next-app && next start"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "12.3.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@~local-docs/esbuild": "file:./local/esbuild",
|
||||
"@~local-docs/tailwind": "file:./local/tailwind",
|
||||
"@types/node": "18.7.20",
|
||||
"@types/react": "18.0.21",
|
||||
"@types/react-dom": "18.0.6",
|
||||
"@typescript-eslint/eslint-plugin": "^5.38.1",
|
||||
"@typescript-eslint/parser": "^5.38.1",
|
||||
"concurrently": "^7.4.0",
|
||||
"esbuild": "^0.15.10",
|
||||
"eslint": "8.24.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
"eslint-config-next": "12.3.1",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-import-resolver-typescript": "^3.5.1",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-json": "^3.1.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-react": "^7.31.8",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-tailwindcss": "^3.6.2",
|
||||
"fast-glob": "^3.2.12",
|
||||
"prettier": "2.7.1",
|
||||
"sass": "^1.55.0",
|
||||
"tailwindcss": "^3.1.8",
|
||||
"typescript": "4.8.3",
|
||||
"wait-on": "^6.0.1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
@font-face {
|
||||
font-family: Noto Sans;
|
||||
src: url('~/assets/font/noto_sans/NotoSans-Regular.ttf') format('truetype');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: Noto Sans;
|
||||
src: url('~/assets/font/noto_sans/NotoSans-SemiBold.ttf') format('truetype');
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: Noto Sans;
|
||||
src: url('~/assets/font/noto_sans/NotoSans-ExtraBold.ttf') format('truetype');
|
||||
font-weight: 800;
|
||||
font-style: normal;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,9 @@
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
export interface PageContainerProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export const PageContainer = ({ children }: PageContainerProps) => (
|
||||
<div className="container">{children}</div>
|
||||
);
|
||||
@@ -0,0 +1,64 @@
|
||||
import '~/assets/css/tailwind.css';
|
||||
import '~/assets/css/styles.css';
|
||||
import Head from 'next/head';
|
||||
import favicon from '~/assets/favicon.ico';
|
||||
import type { AppProps } from 'next/app';
|
||||
|
||||
const OverlayScrollbarsDocs = ({ Component, pageProps }: AppProps) => (
|
||||
<div className="font-sans font-normal">
|
||||
<Head>
|
||||
<title key="title">OverlayScrollbars</title>
|
||||
<meta
|
||||
key="description"
|
||||
name="description"
|
||||
content="A javascript scrollbar plugin that hides native scrollbars, provides custom styleable overlay scrollbars and keeps the native functionality and feeling."
|
||||
/>
|
||||
<link rel="icon" href={favicon.src} />
|
||||
<link rel="shortcut icon" type="image/x-icon" href={favicon.src} />
|
||||
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="theme-color" content="#36befd" />
|
||||
<meta name="msapplication-TileColor" content="#36befd" />
|
||||
<meta name="msapplication-navbutton-color" content="#36befd" />
|
||||
<meta name="application-name" content="OverlayScrollbars" />
|
||||
<meta name="msapplication-tooltip" content="OverlayScrollbars" />
|
||||
<meta name="apple-mobile-web-app-title" content="OverlayScrollbars" />
|
||||
<script
|
||||
type="application/ld+json"
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: JSON.stringify({
|
||||
'@context': 'http://schema.org',
|
||||
'@type': 'SoftwareSourceCode',
|
||||
url: 'https://kingsora.github.io/OverlayScrollbars',
|
||||
name: 'OverlayScrollbars',
|
||||
description:
|
||||
'A javascript scrollbar plugin that hides native scrollbars, provides custom styleable overlay scrollbars and keeps the native functionality and feeling.',
|
||||
license: 'https://en.wikipedia.org/wiki/MIT_License',
|
||||
keywords:
|
||||
'js,javascript,typescript,overlayscrollbars,overlay,scrollbars,custom,scrollbar,plugin,react,vue,angular,treeshaking',
|
||||
isAccessibleForFree: true,
|
||||
image:
|
||||
'https://raw.githubusercontent.com/KingSora/OverlayScrollbars/master/logo/logo.png',
|
||||
codeRepository: 'https://github.com/KingSora/OverlayScrollbars',
|
||||
runtimePlatform: 'browser',
|
||||
maintainer: {
|
||||
'@type': 'Person',
|
||||
name: 'Rene Haas',
|
||||
additionalName: 'KingSora',
|
||||
url: 'https://github.com/KingSora',
|
||||
},
|
||||
programmingLanguage: {
|
||||
'@type': 'ComputerLanguage',
|
||||
name: 'javascript',
|
||||
alternateName: 'js',
|
||||
},
|
||||
}),
|
||||
}}
|
||||
/>
|
||||
</Head>
|
||||
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
|
||||
<Component {...pageProps} />
|
||||
</div>
|
||||
);
|
||||
|
||||
export default OverlayScrollbarsDocs;
|
||||
@@ -0,0 +1,6 @@
|
||||
import { PageContainer } from '~/components/PageContainer';
|
||||
import type { NextPage } from 'next';
|
||||
|
||||
const IndexPage: NextPage = () => <PageContainer>hello</PageContainer>;
|
||||
|
||||
export default IndexPage;
|
||||
@@ -0,0 +1,6 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
// eslint-disable-next-line global-require
|
||||
presets: [require('@~local-docs/tailwind')],
|
||||
content: ['**/*.{js,ts,jsx,tsx}'],
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"extends": "@~local/tsconfig",
|
||||
"compilerOptions": {
|
||||
"incremental": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsx",
|
||||
"paths": {
|
||||
"~/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||
"exclude": ["node_modules", "**/node_modules"]
|
||||
}
|
||||
@@ -6,7 +6,6 @@
|
||||
"esModuleInterop": true,
|
||||
"target": "ESNext",
|
||||
"sourceMap": true,
|
||||
"jsx": "react",
|
||||
"declaration": true,
|
||||
"suppressImplicitAnyIndexErrors": true,
|
||||
"module": "ESNext",
|
||||
|
||||
Generated
+1987
-279
File diff suppressed because it is too large
Load Diff
+4
-1
@@ -1,7 +1,9 @@
|
||||
{
|
||||
"private": true,
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
"packages/*",
|
||||
"docs/*",
|
||||
"local/*"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@~local/browser-testing": "file:./local/browser-testing",
|
||||
@@ -38,6 +40,7 @@
|
||||
"eslint-plugin-json": "^3.1.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.6.1",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-react": "^7.31.10",
|
||||
"glob": "^7.1.6",
|
||||
"istanbul-lib-instrument": "^5.2.0",
|
||||
"jest": "^28.1.3",
|
||||
|
||||
Reference in New Issue
Block a user