SVG.js plugins and RequireJS - svg

I am trying to write an SVG.js plugin to create some dynamic graphics. The site I want to use it in uses requireJS via django-require.
I am struggling to get the plugins to augment the SVG object, exported by SVG.js, properly.
The plugin is modelled after svg.path.js, another SVG.js plugin, and looks something like this:
(function() {
SVG.extend(SVG.Path, {
myGraphicType: function(p){
return this;
}
});
}).call(this);
My plugin will depend on svg.path and svg. svg.path also depends on svg. The shim entry in the requireJS config looks like:
shim: {
'svg-0.32' : {
exports: 'SVG'
},
'svg.path': {
deps: ['svg-0.32']
},
'svg.myplugin': { //My plugin!
deps: ['svg-0.32', 'svg.path']
}
}
The main app is defined() to depend on both svg and svg.myplugin. However, when I come to use the plugin like this:
var myGraphic = SVG.path().myGraphicType()
I am told that SVG is not defined in the svg.myplugin.js file.
What is the right way to include plugins like this using requireJS?

Related

What is the correct way to build multi-color template using Tailwind CSS?

Creating a custom color scheme for a template is very easy in Tailwind CSS. You just modify tailwind.config.js, add your custom color palate, and use it just like Tailwind's ordinary classes. For example bg-brand-500:
theme: {
extend: {
colors: {
brand: {
'50': '#B0ECEC',
'100': '#A0E8E8',
'200': '#7FE1E1',
'300': '#5ED9D9',
'400': '#3DD1D1',
'500': '#2CB9B9',
'600': '#218C8C',
'700': '#165E5E',
'800': '#0C3131',
'900': '#010404'
},
}
}
}
Now I'm stuck at a way to make a multi-color template.
I'm sure you have all seen templates all over the web where you can choose red or blue for example and the entire template's color scheme changes.
How do you do that in Tailwind?
Update:
In other CSS schools, like SASS, you simply create another color variables file and dynamically load a different file using the regular <link href='/path/to/red/variables.css' />.
You can use CSS variables for that.
In your tailwind config, you create the brand colors as you did, but instead of hex color codes, you use for example 50: 'var(--brand-50)'. Then in your index.css you can add these variables to the base layer, like:
#layer base {
:root {
--brand-50: #B0ECEC;
}
.theme-red {
--brand-50: #BB0000;
}
}
Now, if you add the class .theme-red to your body, text-brand-50 will be red.
In this video of Tailwind labs it is fully explained. There is also explained how to deal with opacity, although since tailwind 3.1 there is an easier way of doing that.
Hope this helps.
You might use the tw-colors plugin.
Create your themes
const { createThemes } = require('tw-colors');
module.exports = {
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
plugins: [
createThemes({
light: {
brand: {
'50': '#B0ECEC',
'100': '#A0E8E8',
'200': '#7FE1E1',
'300': '#5ED9D9',
'400': '#3DD1D1',
'500': '#2CB9B9',
'600': '#218C8C',
'700': '#165E5E',
'800': '#0C3131',
'900': '#010404'
},
},
dark: {
brand: {
'50': '#321321',
'100': '#654654',
'200': '#987987',
'300': '#786541',
'400': '#aeeeee',
'500': '#786541',
'600': '#987987',
'700': '#165E5E',
'800': '#654654',
'900': '#321321'
},
}
})
],
};
Use your themes
<html class='theme-light'>
<div class="bg-brand-500">...</div>
</html>
You can then switch themes dynamically as you like, with a switch for example

Is there a way to minify css classNames?

I wanna make some obfuscation and minification by changing my css class-names. As I don't think this is a right way to minify it by myself, so I'm using css modules with
getLocalIdent: MinimalClassnameGenerator({ length: 1 })
//where MinimalClassnameGenerator is webpack-minimal-classnames
and it works at css side, class names is minified. But unfortunately at output.bundle.js I've found lines like this
const N = { class: "super-puper-class" },
[
"__cssModules",
{
$style: {
"super-puper-class": "J",
It means that only css side is minified and somebody could know real class name after compilation. Is there a way to minify and obfuscate classNames right?

Use different loader in Webpack depending on from where I'm importing

I'm using the svg loader to import SVG icons in my React file.
webpack.config.js:
{ test: /\.svg(\?.*)?$/, loader: 'svg' }
component.js:
import Icon from './icon.svg'
render () {
return <svg {...Icon.attributes} dangerouslySetInnerHTML={{ __html: Icon.content }} />
}
So far I have no issues. I also want to use SVG images in my CSS. If I do this:
.class {
background-image: url('./icon.svg');
}
My final result looks like this:
I would like to use the url loader for my CSS file. I tried this:
.class {
url('url!./icon.svg?name=[path][name].[ext]&limit=1&mimetype=image/svg+xml');
}
In my CSS I get:
This looks like what I want but the image is not displayed and if I open the url in a separate tab I get this:
Which leads me to think that the svg loader is still running.
Is there a way to specify a different loader based on from which file I'm importing?
Add issuer see: webpack.js.org/configuration/module/#rule-issuer
An example:
{
test: /\.svg(\?.*)?$/,
issuer: /\.js$/,
loader: 'svg-inline-loader',
},
{
test: /\.svg/,
issuer: /\.scss$/,
use: {
loader: 'svg-url-loader',
options: {},
},
},
I'm not sure that's exactly what you need; it sounds like you need to trigger webpack's module resolution. By default, the CSS loader treats image URL references as relative (like they would normally be w/CSS). You need to prefix the URL with a '~' to tell it to use webpack's require resolution to find the module.

Load "on the fly" code with requirejs

I'm trying to create an online interactive js programming test-bed. I have a code window and a target iframe where the code gets loaded to execute. I wrap the code in html and load it into the iframe. The problem is that the code I want to be testing is normally loaded via requirejs using a data-main parameter. It appears that the code needs to be loaded from a separate file so that I can't include it in the html itself.
What works but doesn't help me is creating a file on the server to use as the target of the data-main parameter and sending html to the iframe that requires requirejs and then loads my code.
html:
<html>
....
<script type="text/javascript" src="lib/requirejs/require.js" data-main="src/requireConfigTest"></script>
....
</html>
contents of requireConfigTest.js:
/*globals require*/
require.config({
shim: {
},
paths: {
famous: 'lib/famous',
requirejs: 'lib/requirejs/require',
almond: 'lib/almond/almond',
'famous-polyfills': 'lib/famous-polyfills/index'
}
});
// this is the injection point where the dynamic code starts
define(function (require,exports,module) {
var Engine = require("famous/core/Engine");
var Surface = require("famous/core/Surface");
var mainContext = Engine.createContext();
var surface = new Surface({
size: [100, 100],
content: "Hello World",
classes: ["red-bg"],
properties: {
textAlign: "center",
lineHeight: "20px"
}
});
alert('hi');
mainContext.add(surface);
});
//this is the end of the dynamic code
This requires writing the dynamic code back to the server, not a reasonable solution. I'm trying to implement something like this...
html:
<html>
....
<script type="text/javascript" src="lib/requirejs/require.js"</script>
<script type="text/javascript">
/*globals require*/
require.config({
shim: {
},
paths: {
famous: 'lib/famous',
requirejs: 'lib/requirejs/require',
almond: 'lib/almond/almond',
'famous-polyfills': 'lib/famous-polyfills/index'
}
});
// this is the injection point where the dynamic code starts
define(function (require,exports,module) {
var Engine = require("famous/core/Engine");
var Surface = require("famous/core/Surface");
var mainContext = Engine.createContext();
var surface = new Surface({
size: [100, 100],
content: "Hello World",
classes: ["red-bg"],
properties: {
textAlign: "center",
lineHeight: "20px"
}
});
alert('hi');
mainContext.add(surface);
});
//this is the end of the dynamic code
</script>
This fails with the message:
Uncaught Error: Mismatched anonymous define() module: function
(require, exports, module) {...
My hope is to either find a way to reformat the code above in the second script tag or find a way to pass the actual contents of requireConfigTest.js via data-main instead of passing the name of the file to load.
Any help here would be greatly appreciated.
Since you are not actually defining a module with your define call, you could just use require:
require(["famous/core/Engine", "famous/core/Surface"], function (Engine, Surface) {
var mainContext = Engine.createContext();
// Etc...
You can think of define as being a require call which additionally defines a module. The way you are using define it is defining a module that does not have a name because you did not give it a name (which is generally the right thing to do) but it is not loaded from a .js file. When you don't give a name to a module as the first argument of define, RequireJS assigns a name from the .js file it loads the module from.
Another thing to keep in mind is that require schedules its callback for execution right away. (The callback is not executed right away but it scheduled for execution right away.) Whereas define does not schedule anything. It just records the callback and then when a require call (or something equivalent) requires it, the callback is executed.

curious dependency loading behaviour in requirejs

I've been having trouble loading dependencies in requirejs, so have tried to recreate the simplest possible structure that shows my problem. The html file contains a bootstrap typeahead box that I want to fill with data once the page loads. If my main.js script is:
requirejs.config({
paths: {
jquery: 'libs/jquery/jquery-min',
bootstrap: 'libs/bootstrap/bootstrap.min',
underscore: 'libs/underscore/underscore-min',
backbone: 'libs/backbone/backbone-optamd3-min',
cs: 'libs/require/cs',
'coffee-script': 'libs/coffeescript/coffee-script'
},
shim: {
bootstrap: {
deps: ['jquery']
}
});
require(['cs!router']);
and my backbone entry point is a very simple router:
define ['jquery','underscore','backbone','bootstrap'], ($, _, Backbone) ->
AppRouter = Backbone.Router.extend
initialize: () ->
#data = ['one','two','three']
routes: '': 'index'
index: () ->
$('.typeahead').typeahead({source:#data})
app_router = new AppRouter
Backbone.history.start()
then if the page loads from a cleaned webcache, I get the following errors on the console:
TypeError: a is not a function
TypeError: $(".typeahead").typeahead is not a function
Error: Load timeout for modules: cs!router
http://requirejs.org/docs/errors.html#timeout
If I simply reload the page, all the errors disappear and everything works ok. I'd be really grateful if someone could explain to me what is happening here, thanks.
Ok, fixed by using
<script data-main="js/main" src="js/libs/require/require-jquery.js"></script>
instead of
<script data-main="js/main" src="js/libs/require/require.js"></script>
in main html file.

Resources