Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multiple source paths. #338

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
34 changes: 27 additions & 7 deletions packages/create-react-kotlin-app/createReactApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,21 @@ const packageJson = require('./package.json');

let projectName;

function collectLayout(value, layout) {
const items = value.split(',');
items.forEach(item => updateLayout(layout, item));
return layout;
}

function updateLayout(layout, config) {
const items = config.split('=');
if (items.length == 2) {
layout[items[0]] = items[1];
} else {
console.warn(`Invalid layout config ignored: ${chalk.green(config)}`);
}
}

const program = new commander.Command(packageJson.name)
.version(packageJson.version)
.arguments('<project-directory>')
Expand All @@ -63,6 +78,12 @@ const program = new commander.Command(packageJson.name)
'--scripts-version <alternative-package>',
'use a non-standard version of react-scripts'
)
.option(
'--layout <layout>',
'custom project layout config. e.g. src=frontend',
collectLayout,
{}
)
.allowUnknownOption()
.on('--help', () => {
console.log(` Only ${chalk.green('<project-directory>')} is required.`);
Expand Down Expand Up @@ -156,6 +177,9 @@ function createApp(name, verbose, version, template) {
name: appName,
version: '0.1.0',
private: true,
kotlin: {
src: program.layout.src || 'src',
},
};
fs.writeFileSync(
path.join(root, 'package.json'),
Expand All @@ -167,9 +191,7 @@ function createApp(name, verbose, version, template) {
if (!semver.satisfies(process.version, '>=6.0.0')) {
console.log(
chalk.yellow(
`You are using Node ${
process.version
} so the project will be boostrapped with an old unsupported version of tools.\n\n` +
`You are using Node ${process.version} so the project will be boostrapped with an old unsupported version of tools.\n\n` +
`Please update to Node 6 or higher for a better, fully supported experience.\n`
)
);
Expand All @@ -184,9 +206,7 @@ function createApp(name, verbose, version, template) {
if (npmInfo.npmVersion) {
console.log(
chalk.yellow(
`You are using npm ${
npmInfo.npmVersion
} so the project will be boostrapped with an old unsupported version of tools.\n\n` +
`You are using npm ${npmInfo.npmVersion} so the project will be boostrapped with an old unsupported version of tools.\n\n` +
`Please update to npm 3 or higher for a better, fully supported experience.\n`
)
);
Expand Down Expand Up @@ -296,7 +316,7 @@ function run(
'init.js'
);
const init = require(scriptsPath);
init(root, appName, verbose, originalDirectory, template);
init(root, appName, verbose, originalDirectory, template, program.layout);

if (version === 'react-scripts@0.9.x') {
console.log(
Expand Down
9 changes: 7 additions & 2 deletions packages/react-scripts/config/paths.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ const resolveApp = relativePath => path.resolve(appDirectory, relativePath);

const envPublicUrl = process.env.PUBLIC_URL;

function resolveCfg(name, defaults) {
const json = require(resolveApp('package.json')).kotlin || {};
return json[name] || defaults;
}

function ensureSlash(path, needsSlash) {
const hasSlash = path.endsWith('/');
if (hasSlash && !needsSlash) {
Expand Down Expand Up @@ -53,7 +58,7 @@ module.exports = {
appPublic: resolveApp('public'),
appHtml: resolveApp('public/index.html'),
appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'),
appSrc: [].concat(resolveCfg('src', 'src')).map(resolveApp),
yarnLockFile: resolveApp('yarn.lock'),
appNodeModules: resolveApp('node_modules'),
publicUrl: getPublicUrl(resolveApp('package.json')),
Expand All @@ -73,7 +78,7 @@ module.exports = {
appPublic: resolveApp('public'),
appHtml: resolveApp('public/index.html'),
appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'),
appSrc: [].concat(resolveCfg('src', 'src')).map(resolveApp),
yarnLockFile: resolveApp('yarn.lock'),
appNodeModules: resolveApp('node_modules'),
publicUrl: getPublicUrl(resolveApp('package.json')),
Expand Down
18 changes: 12 additions & 6 deletions packages/react-scripts/config/webpack.config.dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ const env = getClientEnvironment(publicUrl);
// The production configuration is different and lives in a separate file.

const kotlinModuleName = 'kotlinApp';
const sourcePaths = {};
[]
.concat(paths.appSrc)
.forEach(source => (sourcePaths[path.basename(source)] = source));

module.exports = {
// You may want 'eval' instead if you prefer to see the compiled output in DevTools.
Expand Down Expand Up @@ -97,12 +101,14 @@ module.exports = {
// some tools, although we do not recommend using it, see:
// https://github.com/facebookincubator/create-react-app/issues/290
extensions: ['.js', '.json', '.jsx'],
alias: {
// Support React Native Web
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
'react-native': 'react-native-web',
src: paths.appSrc,
},
alias: Object.assign(
{
// Support React Native Web
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
'react-native': 'react-native-web',
},
sourcePaths
),
},
module: {
strictExportPresence: true,
Expand Down
29 changes: 21 additions & 8 deletions packages/react-scripts/config/webpack.config.prod.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ if (env.stringified['process.env'].NODE_ENV !== '"production"') {
}

const kotlinModuleName = 'kotlinApp';
const sourcePaths = {};
[]
.concat(paths.appSrc)
.forEach(source => (sourcePaths[path.basename(source)] = source));

// This is the production configuration.
// It compiles slowly and is focused on producing a fast and minimal bundle.
Expand All @@ -62,8 +66,15 @@ module.exports = {
// We inferred the "public path" (such as / or /my-project) from homepage.
publicPath: publicPath,
// Point sourcemap entries to original disk location
devtoolModuleFilenameTemplate: info =>
path.relative(paths.appSrc, info.absoluteResourcePath),
devtoolModuleFilenameTemplate: function(info) {
for (const index in paths.appSrc) {
const src = paths.appSrc[index];
const relative = path.relative(src, info.absoluteResourcePath);
if (!path.isAbsolute(relative)) {
return relative;
}
}
},
},
resolve: {
// This allows you to set a fallback for where Webpack should look for modules.
Expand All @@ -83,12 +94,14 @@ module.exports = {
// some tools, although we do not recommend using it, see:
// https://github.com/facebookincubator/create-react-app/issues/290
extensions: ['.js', '.json', '.jsx'],
alias: {
// Support React Native Web
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
'react-native': 'react-native-web',
src: paths.appSrc,
},
alias: Object.assign(
{
// Support React Native Web
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
'react-native': 'react-native-web',
},
sourcePaths
),
},
module: {
strictExportPresence: true,
Expand Down
42 changes: 40 additions & 2 deletions packages/react-scripts/scripts/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,45 @@ const path = require('path');
const chalk = require('chalk');
const spawn = require('react-dev-utils/crossSpawn');

function customLayout(appPath, layout) {
for (const key in layout) {
const value = layout[key];
const file = path.join(appPath, key);
try {
fs.renameSync(file, path.join(appPath, value));
} catch (e) {
console.error(`${file} is not exists`);
}
}
format(appPath, layout);
}

function format(filePath, params) {
const stat = fs.statSync(filePath);
if (stat.isDirectory()) {
return fs
.readdirSync(filePath, { withFileTypes: true })
.filter(item => ['node_modules', '.git'].indexOf(item.name) == -1)
.forEach(item => format(path.join(filePath, item.name), params));
}
const buffer = fs.readFileSync(filePath);
let changed = false;
const content = buffer.toString().replace(/\{\{(\w+)\}\}/g, function(m, w) {
changed = true;
return Object.prototype.hasOwnProperty.call(params, w) ? params[w] : w;
});
if (changed) {
fs.writeFileSync(filePath, content);
}
}

module.exports = function(
appPath,
appName,
verbose,
originalDirectory,
template
template,
layout
) {
const ownPackageName = require(path.join(__dirname, '..', 'package.json'))
.name;
Expand All @@ -42,7 +75,10 @@ module.exports = function(
build: 'react-scripts-kotlin build',
eject: 'react-scripts-kotlin eject',
'gen-idea-libs': 'react-scripts-kotlin gen-idea-libs',
'get-types': 'react-scripts-kotlin get-types --dest=src/types',
'get-types':
'react-scripts-kotlin get-types --dest=' +
[].concat(layout.src)[0] +
'/types',
postinstall: 'npm run gen-idea-libs',
};

Expand Down Expand Up @@ -84,6 +120,8 @@ module.exports = function(
fs.writeFileSync(modulesPath, modules.replace(/%appName%/g, appName));
}

customLayout(appPath, layout);

// Rename gitignore after the fact to prevent npm from renaming it to .npmignore
// See: https://github.com/npm/npm/issues/1862
fs.move(
Expand Down
2 changes: 1 addition & 1 deletion packages/react-scripts/template-idea/template-idea.iml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/{{src}}" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
Expand Down
2 changes: 1 addition & 1 deletion packages/react-scripts/template/src/index/index.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import react.dom.*
import kotlin.browser.*

fun main(args: Array<String>) {
requireAll(require.context("src", true, js("/\\.css$/")))
requireAll(require.context("{{src}}", true, js("/\\.css$/")))
zeroify marked this conversation as resolved.
Show resolved Hide resolved

render(document.getElementById("root")) {
app()
Expand Down
4 changes: 2 additions & 2 deletions packages/react-scripts/template/src/logo/Logo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import react.dom.*
import kotlinext.js.*
import kotlinx.html.style

@JsModule("src/logo/react.svg")
@JsModule("{{src}}/logo/react.svg")
external val reactLogo: dynamic
@JsModule("src/logo/kotlin.svg")
@JsModule("{{src}}/logo/kotlin.svg")
external val kotlinLogo: dynamic

fun RBuilder.logo(height: Int = 100) {
Expand Down