Skip to content

Loading uikit resources via the Node resolver #1246

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

Merged
merged 7 commits into from
Aug 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"publish": "npx lerna publish -m \"[skip travis] chore(release): publish %s\"",
"postpublish": "auto release",
"preview:docs": "cd packages/docs && yarn production",
"preview:hbs": "cd packages/development-edition-engine-handlebars && npx patternlab add --starterkits @pattern-lab/starterkit-handlebars-vanilla && npm run pl:build"
"preview:hbs": "cd packages/development-edition-engine-handlebars && yarn pl:starterkit && yarn pl:build"
},
"nyc": {
"exclude": [
Expand Down
22 changes: 12 additions & 10 deletions packages/cli/bin/install-edition.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ const {
writeJsonAsync,
getJSONKey,
} = require('./utils');
const {
resolveFileInPackage,
resolveDirInPackage,
} = require('@pattern-lab/core/src/lib/resolver');

// https://github.com/TehShrike/deepmerge#overwrite-array
const overwriteMerge = (destinationArray, sourceArray, options) => sourceArray;
Expand All @@ -31,7 +35,7 @@ const installEdition = (edition, config, projectDir) => {
const sourceDir = config.paths.source.root;
yield checkAndInstallPackage(edition); // 1
yield copyAsync(
path.resolve('./node_modules', edition, 'source', '_meta'),
resolveDirInPackage(edition, 'source', '_meta'),
path.resolve(sourceDir, '_meta')
); // 2
pkg.dependencies = Object.assign(
Expand All @@ -45,16 +49,15 @@ const installEdition = (edition, config, projectDir) => {
// 4.1
case '@pattern-lab/edition-node-gulp': {
yield copyAsync(
path.resolve('./node_modules', edition, 'gulpfile.js'),
resolveFileInPackage(edition, 'gulpfile.js'),
path.resolve(sourceDir, '../', 'gulpfile.js')
);
break;
}
// 4.2
case '@pattern-lab/edition-node': {
const editionPath = path.resolve('./node_modules', edition);
const editionConfigPath = path.resolve(
editionPath,
const editionConfigPath = resolveFileInPackage(
edition,
'patternlab-config.json'
);

Expand All @@ -67,7 +70,7 @@ const installEdition = (edition, config, projectDir) => {
);

yield copyAsync(
path.join(editionPath, path.sep, 'helpers', path.sep, 'test.js'),
resolveFileInPackage(edition, 'helpers', 'test.js'),
path.resolve(sourceDir, '../', 'helpers/test.js')
);

Expand All @@ -76,9 +79,8 @@ const installEdition = (edition, config, projectDir) => {
}
// 4.3
case '@pattern-lab/edition-twig': {
const editionPath = path.resolve('./node_modules', edition);
const editionConfigPath = path.resolve(
editionPath,
const editionConfigPath = resolveFileInPackage(
edition,
'patternlab-config.json'
);
const editionConfig = require(editionConfigPath);
Expand All @@ -90,7 +92,7 @@ const installEdition = (edition, config, projectDir) => {
);

yield copyAsync(
path.resolve(editionPath, 'alter-twig.php'),
resolveFileInPackage(edition, 'alter-twig.php'),
path.resolve(sourceDir, '../', 'alter-twig.php')
);

Expand Down
10 changes: 3 additions & 7 deletions packages/cli/bin/install-plugin.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
'use strict';

const path = require('path');

const _ = require('lodash');

const checkAndInstallPackage = require('./utils').checkAndInstallPackage;
const wrapAsync = require('./utils').wrapAsync;
const { checkAndInstallPackage, wrapAsync } = require('./utils');
const { resolveFileInPackage } = require('@pattern-lab/core/src/lib/resolver');

const installPlugin = (plugin, config) =>
wrapAsync(function*() {
Expand All @@ -16,9 +14,7 @@ const installPlugin = (plugin, config) =>
_.set(config, `plugins[${name}]['initialized']`, false);

// Get the options from the plugin, if any
const pluginPathConfig = path.resolve(
path.join(process.cwd(), 'node_modules', name, 'config.json')
);
const pluginPathConfig = resolveFileInPackage(name, 'config.json');
try {
const pluginConfigJSON = require(pluginPathConfig);
if (!_.has(config.plugins[name].options)) {
Expand Down
12 changes: 9 additions & 3 deletions packages/cli/bin/install-starterkit.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,22 @@ const {
checkAndInstallPackage,
readJsonAsync,
} = require('./utils');
const {
resolvePackageFolder,
resolveDirInPackage,
} = require('@pattern-lab/core/src/lib/resolver');

const installStarterkit = (starterkit, config) =>
wrapAsync(function*() {
const sourceDir = config.paths.source.root;
const name = starterkit.value || starterkit;
yield checkAndInstallPackage(name);
const kitPath = path.resolve('./node_modules', name);
yield copyAsync(path.resolve(kitPath, 'dist'), path.resolve(sourceDir));
yield copyAsync(resolveDirInPackage(name, 'dist'), path.resolve(sourceDir));
let kitConfig;
const kitConfigPath = path.resolve(kitPath, 'patternlab-config.json');
const kitConfigPath = path.join(
resolvePackageFolder(name),
'patternlab-config.json'
);
if (fs.existsSync(kitConfigPath)) {
kitConfig = yield readJsonAsync(kitConfigPath);
}
Expand Down
5 changes: 3 additions & 2 deletions packages/cli/bin/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const path = require('path');
const chalk = require('chalk');
const EventEmitter = require('events').EventEmitter;
const hasYarn = require('has-yarn');
const { resolveFileInPackage } = require('@pattern-lab/core/src/lib/resolver');

/**
* @name log
Expand Down Expand Up @@ -124,7 +125,7 @@ const copyWithPattern = (cwd, pattern, dest) =>

/**
* @func fetchPackage
* @desc Fetches and saves packages from npm into node_modules and adds a reference in the package.json under dependencies
* @desc Fetches packages from an npm package registry and adds a reference in the package.json under dependencies
* @param {string} packageName - The package name
*/
const fetchPackage = packageName =>
Expand Down Expand Up @@ -193,7 +194,7 @@ const getJSONKey = (packageName, key, fileName = 'package.json') =>
wrapAsync(function*() {
yield checkAndInstallPackage(packageName);
const jsonData = yield fs.readJson(
path.resolve('node_modules', packageName, fileName)
resolveFileInPackage(packageName, fileName)
);
return jsonData[key];
});
Expand Down
1 change: 1 addition & 0 deletions packages/core/patternlab-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
"uikits": [
{
"name": "uikit-workshop",
"package": "@pattern-lab/uikit-workshop",
"outputDir": "",
"enabled": true,
"excludedPatternStates": [],
Expand Down
6 changes: 2 additions & 4 deletions packages/core/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ const patternlab_module = function(config) {
},

/**
* Installs plugin already available via `node_modules/`
* Installs plugin already available as a package dependency
*
* @memberof patternlab
* @name installplugin
Expand All @@ -214,8 +214,6 @@ const patternlab_module = function(config) {
* @returns {void}
*/
installplugin: function(pluginName) {
//get the config
const configPath = path.resolve(process.cwd(), 'patternlab-config.json');
const plugin_manager = new pm();

plugin_manager.install_plugin(pluginName);
Expand All @@ -234,7 +232,7 @@ const patternlab_module = function(config) {
},

/**
* Loads starterkit already available via `node_modules/`
* Loads starterkit already available as a package dependency
*
* @memberof patternlab
* @name loadstarterkit
Expand Down
117 changes: 68 additions & 49 deletions packages/core/src/lib/loaduikits.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,91 +5,110 @@ const _ = require('lodash');

const logger = require('./log');

let findModules = require('./findModules'); //eslint-disable-line prefer-const
let fs = require('fs-extra'); // eslint-disable-line

const uiKitMatcher = /^uikit-(.*)$/;
const nodeModulesPath = path.join(process.cwd(), 'node_modules');

/**
* Given a path: return the uikit name if the path points to a valid uikit
* module directory, or false if it doesn't.
* @param filePath
* @returns UIKit name if exists or FALSE
*/
const isUIKitModule = filePath => {
const baseName = path.basename(filePath);
const engineMatch = baseName.match(uiKitMatcher);
const { resolvePackageFolder } = require('./resolver');

if (engineMatch) {
return engineMatch[1];
}
return false;
};
let fs = require('fs-extra'); // eslint-disable-line

const readModuleFile = (kit, subPath) => {
const readModuleFile = (uikitLocation, subPath) => {
return fs.readFileSync(
path.resolve(path.join(kit.modulePath, subPath)),
path.resolve(path.join(uikitLocation, subPath)),
'utf8'
);
};

/**
* Loads uikits, connecting configuration and installed modules
* [1] Looks in node_modules for uikits.
* [2] Filter out our uikit-polyfills package.
* [3] Only continue if uikit is enabled in patternlab-config.json
* [1] Lists the enabled uikits from patternlab-config.json
* [2] Try to resolve the location of the uikit in the package dependencies
* [3] Warn when the uikit couldn't be loaded
* [4] Reads files from uikit that apply to every template
* @param {object} patternlab
*/
module.exports = patternlab => {
const paths = patternlab.config.paths;

const uikits = findModules(nodeModulesPath, isUIKitModule) // [1]
.filter(kit => kit.name !== 'polyfills'); // [2]
uikits.forEach(kit => {
const configEntry = _.find(_.filter(patternlab.config.uikits, 'enabled'), {
name: `uikit-${kit.name}`,
}); // [3]

if (!configEntry) {
logger.warning(
`Could not find uikit with name uikit-${kit.name} defined within patternlab-config.json, or it is not enabled.`
);
return;
const uikitConfigs = _.filter(patternlab.config.uikits, 'enabled'); // [1]
uikitConfigs.forEach(uikitConfig => {
let uikitLocation = null;
if ('package' in uikitConfig) {
try {
uikitLocation = resolvePackageFolder(uikitConfig.package);
} catch (ex) {
logger.warning(
`Could not find uikit with package name ${uikitConfig.package}. Did you add it to the 'dependencies' section in your 'package.json' file?`
);
return;
}
} else {
// For backwards compatibility, name to package calculation is:
// 1. name -> name
// 2. name -> uikit-name
// 3. name -> @pattern-lab/name
// 4. name -> @pattern-lab/uikit-name
for (const packageName of [
Comment on lines +42 to +48
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good fallback

uikitConfig.name,
`uikit-${uikitConfig.name}`,
`@pattern-lab/${uikitConfig.name}`,
`@pattern-lab/uikit-${uikitConfig.name}`,
]) {
try {
uikitLocation = resolvePackageFolder(packageName); // [2]
} catch (ex) {
// Ignore
}
if (uikitLocation != null) {
uikitConfig.package = packageName;
logger.info(`Found uikit package ${packageName}`);
break;
}
}
if (uikitLocation == null) {
logger.warning(
`Could not find uikit with package name ${uikitConfig.name}, uikit-${uikitConfig.name}, @pattern-lab/${uikitConfig.name} or @pattern-lab/uikit-${uikitConfig.name} defined within patternlab-config.json in the package dependencies.`
);
return;
} else {
logger.warning(
`Please update the configuration of UIKit ${uikitConfig.name} with property 'package: ${uikitConfig.package}' in patternlab-config.json. Lookup by 'name' is deprecated and will be removed in the future.`
);
} // [3]
Comment on lines +70 to +74
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good message as info for the user

}

try {
patternlab.uikits[`uikit-${kit.name}`] = {
name: `uikit-${kit.name}`,
modulePath: kit.modulePath,
patternlab.uikits[uikitConfig.name] = {
name: uikitConfig.name,
package: uikitConfig.package,
modulePath: uikitLocation,
enabled: true,
outputDir: configEntry.outputDir,
excludedPatternStates: configEntry.excludedPatternStates,
excludedTags: configEntry.excludedTags,
outputDir: uikitConfig.outputDir,
excludedPatternStates: uikitConfig.excludedPatternStates,
excludedTags: uikitConfig.excludedTags,
header: readModuleFile(
kit,
uikitLocation,
paths.source.patternlabFiles['general-header']
),
footer: readModuleFile(
kit,
uikitLocation,
paths.source.patternlabFiles['general-footer']
),
patternSection: readModuleFile(
kit,
uikitLocation,
paths.source.patternlabFiles.patternSection
),
patternSectionSubType: readModuleFile(
kit,
uikitLocation,
paths.source.patternlabFiles.patternSectionSubtype
),
viewAll: readModuleFile(kit, paths.source.patternlabFiles.viewall),
viewAll: readModuleFile(
uikitLocation,
paths.source.patternlabFiles.viewall
),
}; // [4]
} catch (ex) {
logger.error(ex);
logger.error(
'\nERROR: missing an essential file from ' +
kit.modulePath +
uikitLocation +
paths.source.patternlabFiles +
". Pattern Lab won't work without this file.\n"
);
Expand Down
33 changes: 33 additions & 0 deletions packages/core/src/lib/resolver.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
'use strict';

const path = require('path');

/**
* @func resolveFileInPackage
* Resolves a file inside a package
*/
const resolveFileInPackage = (packageName, ...pathElements) => {
return require.resolve(path.join(packageName, ...pathElements));
};
Comment on lines +9 to +11
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked the spread syntax. It is available since Node V8.x


/**
* @func resolvePackageFolder
* Resolves the location of a package on disc
*/
const resolvePackageFolder = packageName => {
return path.dirname(resolveFileInPackage(packageName, 'package.json'));
};

/**
* @func resolveDirInPackage
* Resolves a file inside a package
*/
const resolveDirInPackage = (packageName, ...pathElements) => {
return path.join(resolvePackageFolder(packageName), ...pathElements);
};

module.exports = {
resolveFileInPackage,
resolveDirInPackage,
resolvePackageFolder,
};
2 changes: 1 addition & 1 deletion packages/core/src/lib/starterkit_manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const starterkit_manager = function(config) {
kitDirStats = fs.statSync(kitPath);
} catch (ex) {
logger.warning(
`${starterkitName} not found, use npm to install it first.`
`${starterkitName} not found, use npm or another package manager to install it first.`
);
logger.warning(`${starterkitName} not loaded.`);
return;
Expand Down
Loading