Nrwl NX enforce-module-boundaries - rule if lib does NOT have source tag? - nrwl-nx

We are trying to setup a lib in NX with a scope:example tag, such that it can only be imported by other libs with a scope:example tag.
We were hoping to set it up like this:
{
"sourceTag": "scope:example",
"onlyDependOnLibsWithTags": ["scope:example"]
},
{
"sourceTag": "*",
"notDependOnLibsWithTags": ["scope:example"]
}
This doesn't work, because the 2nd rule applies even to the scope:example libs, preventing them from importing other scope:example libs.
We could fix this by adding a new tag to all of our existing libs, so we can replace the * in the second rule with that new tag.
This is not ideal, because if other devs make libs, the rule will not be enforced unless they manually add the new tag to it.
What would be ideal is something like:
{
"sourceTag": "scope:example",
"onlyDependOnLibsWithTags": ["scope:example"]
},
{
"libsNotContainingSourceTag": "scope:example",
"notDependOnLibsWithTags": ["scope:example"]
}
Any help on any means to achieve the desired lint rule? Thanks in advance!

Related

How to exclude UnityEditor reference from asmdef?

How to exclude UnityEditor reference from asmdef?
Why I need it:
I have an asmdef file. For example, it is MyAssembly/MyAssembly.asmdef. The MyAssembly contains a lot of features and each feature staff is placed in its own folder. And some of these features has a code that is needed only in editor, and it refers to UnityEditor namespace. Such editor code is placed into an Editor folder.
But as you know, Editor folder name means nothing in terms of asmdef usage. So I add AssemblyDefenitionReference in each folder and refer it to the MyAssemblyEditor.asmdef assembly definition. So the paths looks like this:
MyAssembly/MyAssembly.asmdef
MyAssembly/Editor/MyAssemblyEditor.asmdef - this folder contains no code. It's needed just to place asmdef, because it's not allowed to place two asmdefs in a single folder.
MyAssembly/SomeFeature/Editor/*feature editor staff*
MyAssembly/SomeFeature/Editor/Editor.asmref - refers to MyAssemblyEditor.asmdef
MyAssembly/SomeFeature/*feature staff*
All this works good. But the problem is that, when some developer adds a new feature, he can forget to add a reference to the MyAssemblyEditor.asmdef in the editor folder. And there are no any errors will be shown in this case. This mistake will be revealed only when the build will be cooked. But I'd like that using of UnityEditor in MyAssembly will be instantly marked as an error.
Feel free to suggest other solution for this problem.
This thread got me thinking I can use CsprojPostprocessor to remove all references to UnityEditor from my csproj file. I wrote such class:
using System.Text.RegularExpressions;
using UnityEditor;
// ReSharper disable once CheckNamespace
public class CsprojPostprocessor : AssetPostprocessor
{
public static string OnGeneratedCSProject(string path, string content)
{
if (!path.EndsWith("Editor.csproj") && !path.EndsWith("Tests.csproj"))
{
var newContent =
Regex.Replace(content, "<Reference Include=\"UnityEditor(.|\n)*?</Reference>", "");
return newContent;
}
return content;
}
}
It also can be done with an xml parser or something.
The only thing, that confuse me is that this mechanism is badly documented and doesn't look like something simple users should use. So I use it at my own risk, but looks like there is no guarantee it will be strongly supported in future.

How do react-css-modules (babel) and css-loader (webpack) work together?

When using webpack and babel together, one needs to configure both in order to use React CSS Modules. For example:
webpack.config.js will need a rule like this:
{
// Translates CSS into CommonJS modules
loader: 'css-loader',
options: {
modules: {
mode: "local",
localIdentName: CSS_CLASS_NAME_PATTERN,
},
sourceMap: true
}
babel.config.js will need a plugin like this:
[
'react-css-modules',
{
generateScopedName: CSS_CLASS_NAME_PATTERN,
filetypes: {
'.scss': {
syntax: 'postcss-scss',
plugins: ['postcss-nested']
}
},
}
]
Why the need to configure CSS Modules in two places? How the two work together? I.e. what happens in what order?
They don't. css-loader does its own thing: class name transformation in CSS, and replacement of CSS imports in JS code by mappings between original and generated names.
babel-plugin-react-css-modules works independently, and it replaces styleName attributes of react components by className with correct generated names. To do so it calculates class name mappings independently from css-loader, that's why it needs separate configuration matching that of css-loader, and that's why after a few years being abandoned by its creators it has compatibility issues with latest css-loader (css-loader changed internal class name generation logic).
Shameless self-promo: I maintain an up-to-date fork of babel-plugin-react-css-modules which solves compatibility issues with latest css-loader versions.

Babel plugins run order

TL;DR: Is there a way how to specify the order in which the Babel plugins are supposed to be run? How does Babel determine this order? Is there any spec how this works apart from diving into Babel sources?
I'm developing my own Babel plugin. I noticed, that when I run it, my plugin is run before other es2015 plugins. For example having code such as:
const a = () => 1
and visitor such as:
visitor: {
ArrowFunctionExpression(path) {
console.log('ArrowFunction')
},
FunctionExpression(path) {
console.log('Function')
},
}
my plugin observes ArrowFunction (and not Function). I played with the order in which the plugins are listed in Babel configuration, but that didn't change anything:
plugins: ['path_to_myplugin', 'transform-es2015-arrow-functions'],
plugins: ['transform-es2015-arrow-functions', 'path_to_myplugin'],
OTOH, this looks like the order DOES somehow matter:
https://phabricator.babeljs.io/T6719
---- EDIT ----
I found out that if I write my visitor as follows:
ArrowFunctionExpression: {
enter(path) {
console.log('ArrowFunction')
}
},
FunctionExpression: {
exit(path) {
console.log('Function')
}
},
both functions are called. So it looks like the order of execution is: myplugin_enter -> other_plugin -> myplugin_exit. In other words, myplugin seems to be before other_plugin in some internal pipeline. The main question however stays the same - the order of plugins in the pipeline should be determined & configurable somehow.
The order of plugins is based on the order of things in your .babelrc with plugins running before presets, and each group running later plugins/presets before earlier ones.
The key thing though is that the ordering is per AST Node. Each plugin does not do a full traversal, Babel does a single traversal running all plugins in parallel, with each node processed one at a time running each handler for each plugin.
Basically, what #loganfsmyth wrote is correct; there is (probably) no more magic in plugin ordering itself.
As for the my problem specifically, my confusion was caused by how arrow function transformation works. Even if the babel-plugin-transform-es2015-arrow-functions plugin mangles the code sooner than my plugin, it does not remove the original arrow-function ast node from the ast, so even the later plugin sees it.
Learning: when dealing with Babel, don't underestimate the amount of debug print statements needed to understand what's happening.

Configuring ScalaDoc task in Gradle to generate aggregated documentation

I have a multi module scala project in Gradle. Everything works great with it, except the ScalaDoc. I would like to generate a single 'uber-scaladoc' with all of the libraries cross-linked. I'm still very new to groovy/gradle, so this is probably a 'me' problem. Any assistance getting this setup would be greatly appreciated.
build.gradle (in the root directory)
// ...
task doScaladoc(type: ScalaDoc) {
subprojects.each { p ->
// do something here? include the project's src/main/scala/*?
// it looks like I would want to call 'include' in here to include each project's
// source directory, but I'm not familiar enough with the Project type to get at
// that info.
//
// http://www.gradle.org/docs/current/dsl/org.gradle.api.tasks.scala.ScalaDoc.html
}
}
The goal here would be able to just run 'gradle doScalaDoc' at the command line and have the aggregate documentation show up.
Thanks in advance.

CKEditor: how to remove a plugin that has been added?

I'm just beginning to use CKEditor, but have a hard time understanding the plugins system.
I was able to add a simple button that says 'Test' when you click on it with :
var myplugin_function = function () {
alert('Test');
}
var plugin_name='myplugin';
CKEDITOR.plugins.add(plugin_name,
{
init:function(c) {
c.addCommand(plugin_name,myplugin_function);
c.ui.addButton(plugin_name,
{
label:'This is my plugin',
command:plugin_name,
icon:this.path+'myplugin.png'
});
}
});
I know this code should be executed only once, for example in a plugin.js, but that's not how I use it. The CKEditor instance, including my plugin code is executed each time the Ajax-page is loaded.
That's why I use this to remove the instance, if it exists :
if (CKEDITOR.instances['mytextarea']) {
CKEDITOR.remove(CKEDITOR.instances['mytextarea']);
}
Then I use the jquery way to create the ckeditor from a textarea:
$('#mytextarea').ckeditor();
But the 2nd time the ajax-page loads, I get an error about the plugin already being registered. So I need a way to remove the plugin and be able to add it again.
Is this even possible?
UPDATE
This seems to work :
I now check if the plugin is already registered with :
if (!CKEDITOR.plugins.registered[plugin_name]) {
}
around the CKEDITOR.plugins.add(b, ... part
You are not showing how you are adding the plugin, so it's hard to tell what's your exact problem; but from the code that you have provided I can suggest that you use variable names better than "a", "b" and "c". It's quite harder to understand the code this way.
Also, CKEDITOR.remove just removes the instance from the instances array, but it doesn't really clear the used resources, you should use CKEDITOR.instances['mytextarea'].destroy( true ) instead