Testing elm lib with local Native directory - elm

How do we organize our test directory when developing some libraries that uses Native js code?
I tried to work this out, but I'm blocked here, with this error at runtime when running test/test.sh:
Elm.Native.Mylib = {};
^
TypeError: Cannot read property 'Native' of undefined
git repository
My directories are structured this way:
Mylib:
- src :
- Mylib.elm
- Native :
- MyLib.js
- tests :
- Test.elm
- Test.sh
- elm-package.json
the tests/elm-package.json contains :
{
"version": "1.0.0",
"summary": "helpful summary of your project, less than 80 characters",
"repository": "https://github.com/user/project.git",
"license": "BSD3",
"source-directories": [
"."
,"../src"
],
"exposed-modules": [],
"native-modules": true,
"dependencies": {
"elm-community/elm-test": "1.1.0 <= v < 2.0.0",
"elm-lang/core": "4.0.1 <= v < 5.0.0"
},
"elm-version": "0.17.0 <= v < 0.18.0"
}
the tests/Test.elm is :
module Main exposing (..)
import Basics exposing (..)
import ElmTest exposing (..)
import Mylib exposing (..)
tests : Test
tests =
suite "elm-Mylib Library Tests"
[ ]
main =
runSuite tests
The tests/test.sh is
#!/bin/sh
elm-package install -y
elm-make --yes --output test.js Test.elm
node test.js
The src/Mylib.elm is
module Mylib exposing (..)
import Native.Mylib exposing (..)
import Task exposing (Task)
import Time exposing (Time)
print : a -> Task x ()
print value =
Native.Mylib.log (toString value)
getCurrentTime : Task x Time
getCurrentTime =
Native.Mylib.getCurrentTime
The src/Native/Mylib.js is
Elm.Native.Mylib = {};
Elm.Native.Mylib.make = function(localRuntime) {
localRuntime.Native = localRuntime.Native || {};
localRuntime.Native.Mylib = localRuntime.Native.Mylib || {};
if (localRuntime.Native.Mylib.values)
{
return localRuntime.Native.Mylib.values;
}
var Task = Elm.Native.Task.make(localRuntime);
var Utils = Elm.Native.Utils.make(localRuntime);
function log(string)
{
return Task.asyncFunction(function(callback) {
console.log(string);
return callback(Task.succeed(Utils.Tuple0));
});
}
var getCurrentTime = Task.asyncFunction(function(callback) {
return callback(Task.succeed(Date.now()));
});
return localRuntime.Native.Mylib.values = {
log: log,
getCurrentTime: getCurrentTime
};
};

Try this:
var _user$project$Native_MyLib = function() {
return {
exported: function(arg) { return "One" },
exported2: F2(function(arg) { return "Two" }),
exported3: F3(function(arg) { return "Three" }),
}
}();
It works for grater than Elm 0.17.
Buy you should also use full qualified import:
import Natve.MyLib
exported : String -> String
Native.MyLib.exported
exported2 : String -> String -> String
Native.MyLib.exported2
exported3 : String -> String -> String -> String
Native.MyLib.exported3
User and project values are from your/local elm-package.json:
"repository": "https://github.com/user/project.git",

Related

Nested Conditional Properties for Local file references not working in python-jsonschema

My RefResolver and Validator script is
from jsonschema import RefResolver
from jsonschema.validators import validator_for
from tests.automation.io.helpers.loader import load_schema
base = load_schema('base.schema.json') # {"$schema": "http://json-schema.org/draft-07/schema#" }
definitions = load_schema('defination.schema.json') # https://jsonschema.dev/s/FZDbO
schema = load_schema('update.schema.json') # https://jsonschema.dev/s/lvLFa
schema_store = {
base.get('$id','base.schema.json') : base,
definitions.get('$id','defination.schema.json') : definitions,
schema.get('$id','update.schema.json') : schema,
}
resolver = RefResolver.from_schema(base, store=schema_store)
Validator = validator_for(base)
validator = Validator(schema, resolver=resolver)
data = {
"common_data": {
"os_ip": "127.0.0.1",
"os_user": "root",
"os_pwd": "hello",
"remote_os": "Windows"
},
"dup_file": "ad7a.exe"
}
validator.validate(data)
My JSON Schema looks like
base.schema.json => {"$schema": "http://json-schema.org/draft-07/schema#" }
defination.schema.json => https://jsonschema.dev/s/FZDbO
update.schema.json => https://jsonschema.dev/s/lvLFa
Getting error : jsonschema.exceptions.ValidationError: 'ad7a.exe' does not match '^(.*.)(bin)$'
Same thing I have tested https://json-schema.hyperjump.io/ it working perfectly fine , suspecting some issue with python-jsonschema only.

Vue.js: Is it possible to do "Conditional compilation" with a Vue project?

In for example Swift/iOS development, it's possible to differentiate builds for different environments with "flags" such as:
#if STAGING
// one set of logic here
#endif
#if PRODUCTION
// another set of logic here
#endif
Is it possible to achieve the same with a Vue.js project, and how would we go about doing it? I am aware of makes different routes conditionally available for different roles (which is also quite neat), but I am optimally looking for the option to differentiate on a source code level.
Hope someone has some great insights! It could include:
How to exclude parts of a file (such as the #if STAGING above) from a build target
How to exclude entire files from a build target
etc.
you have the ability to use this syntax
if(process.env.NODE_ENV === 'production') {
console.log("this is the prod env!!!!!!!!!!");
config.output.path = path.resolve(__dirname, "dist");
}
make sure that when you run the script with the correct env's for each environment (local, dev, staging, prod etc ..) :D
just change the vue-loader output.
the source code
<template v-if="process.env.NODE_ENV === 'development'">
development only
</template>
default output
var render = function() {
var _vm = this
var _h = _vm.$createElement
var _c = _vm._self._c || _h
return _c(
"div",
{ attrs: { id: "app" } },
[
_vm.process.env.NODE_ENV === "development"
? [_vm._v(" development only ")]
: _vm._e(),
_c("router-view")
],
2
)
}
just use regex to replace _vm.process.env. by process.env is ok.
// webpack.config.js
module: {
rules: [{
// must set post
enforce: 'post',
test: /\.vue$/,
use: [{
loader: './myLoader'
}]
}]
}
// myLoader.js
module.exports = function (source, map) {
if (source.indexOf('_vm.process.env') > -1) {
source = source.replace(/_vm.process.env/g, 'process.env')
}
this.callback(
null,
source,
map
)
}
Final the vue-loader result change
var render = function() {
var _vm = this
var _h = _vm.$createElement
var _c = _vm._self._c || _h
return _c(
"div",
{ attrs: { id: "app" } },
[
// change to true
true
? [_vm._v(" development only ")]
: undefined,
_c("router-view")
],
2
)
}

Load CSS from a dynamically imported ES6 module

My project is being built with Webpack via Laravel Mix. I want to dynamically import an ES6 module that itself imports other modules and a stylesheet. Here is the dynamically imported module (loadJQueryTextillate.js):
import style from 'animate.css/animate.css';
import 'letteringjs';
import 'textillate';
style.use();
export default () => {
};
Here is the module that dynamically imports loadJQueryTextillate.js (animatedText.js):
import isInViewport from './isInViewport';
function maybeAnimateText( elem ) {
const $el = $( elem );
let bounding,
el_html,
el_lines,
in_viewport = $el.data( 'in-viewport' ) || false;
const viewport_height = window.innerHeight || document.documentElement.clientHeight;
if ( $el.hasClass( 'opaque' ) ) {
bounding = elem.getBoundingClientRect();
if ( in_viewport && !isInViewport( elem ) && ( bounding.top > viewport_height ) ) { // Element scrolled off screen
in_viewport = false;
$el.removeClass( 'opaque' ).find( 'ul.texts' ).remove().end().text( $.trim( $el.text() ) );
} else if ( isInViewport( elem ) ) {
in_viewport = true;
}
$el.data( 'in-viewport', in_viewport );
return;
} else if ( !isInViewport( elem ) ) {
return;
}
el_html = $el.html();
el_lines = el_html.split( /<br\s*\/?>/ );
$.each( el_lines, function( key, line ) {
el_lines[ key ] = $.trim( line );
} );
el_html = '<span class="line">' + el_lines.join( '</span><span class="line">' ) + '</span>';
import( /* webpackChunkName: "scripts/jQuery.textillate" */ './loadJQueryTextillate' ).then( () => {
$el.html( el_html ).addClass( 'opaque' ).children( '.line' ).textillate( {
in : {
effect : $el.data( 'in-effect' ) || 'fadeInLeft',
delay : $el.data( 'delay' ) || 12,
},
} );
} );
}
export default () => {
const $els = $( '.tlt' );
if ( 0 === $els.length ) {
return false;
}
$els.each( function( index, elem ) {
maybeAnimateText( elem );
} );
return true;
};
Here is the JS entry script (app.js):
window.$ = window.jQuery = require( 'jquery' );
import 'bootstrap';
import checkAnimatedText from './modules/animatedText';
$( window ).on( 'load', () => {
checkAnimatedText();
} );
Finally, here is the Laravel Mix config script (webpack.mix.js):
const mix = require( 'laravel-mix' );
require( 'laravel-mix-versionhash' );
// Public path helper
const publicPath = path => `${mix.config.publicPath}/${path}`;
// Source path helper
const src = path => `resources/assets/${path}`;
// Public Path
mix
.setPublicPath( './dist' )
.setResourceRoot( `/wp-content/themes/magnetar/${mix.config.publicPath}/` )
.webpackConfig( {
module : {
rules : [ {
test : /animate\.css$/,
use : [ {
loader : "style-loader/useable",
}, { loader : "css-loader" } ],
} ],
},
output : { publicPath : mix.config.resourceRoot },
} );
// Browsersync
mix.browserSync( 'magnetar.localhost' );
// Styles
mix.sass( src`styles/app.scss`, 'styles' );
// Assets
mix.copyDirectory( src`images`, publicPath`images` )
.copyDirectory( src`fonts`, publicPath`fonts` );
// JavaScript
mix.js( src`scripts/app.js`, 'scripts' );
//.extract();
// Autoload
/*mix.autoload( {
jquery : [ '$', 'window.jQuery' ],
} );*/
// Source maps when not in production.
mix.sourceMaps( false, 'source-map' );
// Hash and version files in production.
mix.versionHash( { length : 16 } );
Compiler output:
ERROR in ./node_modules/animate.css/animate.css (./node_modules/css-loader??ref--6-1!./node_modules/postcss-loader/src??ref--6-2!./node_modules/style-loader/useable.js!./node_modules/css-loader!./node_modules/animate.css/animate.css)
Module build failed (from ./node_modules/postcss-loader/src/index.js):
SyntaxError
(1:1) Unknown word
> 1 | var refs = 0;
| ^
2 | var dispose;
3 | var content = require("!!../css-loader/index.js!./animate.css");
EDIT: Updated contents of loadJQueryTextillate.js, webpack.mix.js and compiler output.
You can try style-loader/useable to dynamically load css file. In your script code, you should use style.use() to make style useable or use style.unuse() to make style disable.
The following code shows how you should do to use style-loader/useable.
webpack.config.js
{
module: {
rules: [
{
test: /\.css$/,
exclude: /\.useable\.css$/,
use: [
{ loader: "style-loader" },
{ loader: "css-loader" },
],
},
{
test: /\.useable\.css$/,
use: [
{
loader: "style-loader/useable"
},
{ loader: "css-loader" },
],
},
],
},
}
file you want to dynamically load animate.css
import style form './animate.css';
// make aniamte.css useable
style.use();
// make animate.css disable
style.unuse();

Set programmatically jsonValidation for dynamic mapping

I am creating a new vscode extension, and I need to extend the standard usage of the jsonValidation system already present in vscode.
Note : I am talking about the system defined in package.json :
"contributes" : {
"languages": [
{
"id" : "yml",
"filenamePatterns": ["module.service"]
},
{
"id" : "json",
"filenamePatterns": ["module.*"]
}
],
"jsonValidation": [
{
"fileMatch": "module.test",
"url": "./resources/test.schema"
}
]
}
Now, I need to create a dynamic mapping, where the json fields filematch/url are defined from some internal rules (like version and other internal stuff). The standard usage is static : one fileMatch -> one schema.
I want for example to read the version from the json file to validate, and set the schema after that :
{
"version" : "1.1"
}
validation schema must be test-schema.1.1 instead of test-schema.1.0
note : The question is only about the modification of the configuration provided by package.json from the extensions.ts
Thanks for the support
** EDIT since the previous solution was not working in all cases
There is one solution to modify the package.json at the activating of the function.
export function activate(context: vscode.ExtensionContext) {
const myPlugin = vscode.extensions.getExtension("your.plugin.id");
if (!myPlugin)
{
throw new Error("Composer plugin is not found...")
}
// Get the current workspace path to found the schema later.
const folderPath = vscode.workspace.workspaceFolders;
if (!folderPath)
{
return;
}
const baseUri : vscode.Uri = folderPath[0].uri;
let packageJSON = myPlugin.packageJSON;
if (packageJSON && packageJSON.contributes && packageJSON.contributes.jsonValidation)
{
let jsonValidation = packageJSON.contributes.jsonValidation;
const schemaUri : vscode.Uri = vscode.Uri.joinPath(baseUri, "/schema/value-0.3.0.json-schema");
const schema = new JsonSchemaMatch("value.ospp", schemaUri)
jsonValidation.push(schema);
}
}
And the json schema class
class JsonSchemaMatch
{
fileMatch: string;
url : string;
constructor(fileMatch : string, url: vscode.Uri)
{
this.fileMatch = fileMatch;
this.url = url.path;
}
}
Another important information is the loading of the element of contributes is not reread after modification, for example
class Language
{
id: string;
filenamePatterns : string[];
constructor(id : string, filenamePatterns: string[])
{
this.id = id;
this.filenamePatterns = filenamePatterns;
}
}
if (packageJSON && packageJSON.contributes && packageJSON.contributes.languages)
{
let languages : Language[] = packageJSON.contributes.languages;
for (let language of languages) {
if (language.id == "json") {
language.filenamePatterns.push("test.my-json-type")
}
}
}
This change has no effect, since the loading of file association is already done (I have not dig for the reason, but I think this is the case)
In this case, creating a settings.json in the workspace directory can do the job:
settings.json
{
"files.associations": {
"target.snmp": "json",
"stack.cfg": "json"
}
}
Be aware that the settings.json can be created by the user with legitimate reason, so don't override it, just fill it.

Aurelia CLI font-awesome

I've tried several different solutions but not a single one have worked for me.
I'm using.NET Core, latest Aurelia/Aurelia CLI and Font-Awesome installed using npm install font-awesome --save.
Solution 1:
New file: prepare-font-awesome.js in folder \aurelia_project\tasks
import gulp from 'gulp';
import merge from 'merge-stream';
import changedInPlace from 'gulp-changed-in-place';
import project from '../aurelia.json';
export default function prepareFontAwesome() {
const source = 'node_modules/font-awesome';
const taskCss = gulp.src(`${source}/css/font-awesome.min.css`)
.pipe(changedInPlace({ firstPass: true }))
.pipe(gulp.dest(`${project.platform.output}/css`));
const taskFonts = gulp.src(`${source}/fonts/*`)
.pipe(changedInPlace({ firstPass: true }))
.pipe(gulp.dest(`${project.platform.output}/fonts`));
return merge(taskCss, taskFonts);
}
Updated build.js\aurelia_project\tasks
import prepareFontAwesome from './prepare-font-awesome'; // Our custom task
export default gulp.series(
readProjectConfiguration,
gulp.parallel(
transpile,
processMarkup,
processCSS,
prepareFontAwesome // Our custom task
),
writeBundles
);
Included font-awesome in html
<link rel="stylesheet" href="scripts/css/font-awesome.min.css">
Error:
GET http://localhost:9000/scripts/css/font-awesome.min.css
Solution 2:
Updated aurelia.json
{
"name": "font-awesome",
"path": "../node_modules/font-awesome/",
"main": "",
"resources": [
"css/font-awesome.min.css"
]
}
Added font files in root/font-awesome/fonts
Included font-awesome in html
<require from="font-awesome/css/font-awesome.min.css"></require>
Error: No error but icons are not shown
Solution 3:
Updated build.js:
import gulp from 'gulp';
import transpile from './transpile';
import processMarkup from './process-markup';
import processCSS from './process-css';
import { build } from 'aurelia-cli';
import project from '../aurelia.json';
import fs from 'fs';
import readline from 'readline';
import os from 'os';
export default gulp.series(
copyAdditionalResources,
readProjectConfiguration,
gulp.parallel(
transpile,
processMarkup,
processCSS
),
writeBundles
);
function copyAdditionalResources(done){
readGitIgnore();
done();
}
function readGitIgnore() {
let lineReader = readline.createInterface({
input: fs.createReadStream('./.gitignore')
});
let gitignore = [];
lineReader.on('line', (line) => {
gitignore.push(line);
});
lineReader.on('close', (err) => {
copyFiles(gitignore);
})
}
function copyFiles(gitignore) {
let stream,
bundle = project.build.bundles.find(function (bundle) {
return bundle.name === "vendor-bundle.js";
});
// iterate over all dependencies specified in aurelia.json
for (let i = 0; i < bundle.dependencies.length; i++) {
let dependency = bundle.dependencies[i];
let collectedResources = [];
if (dependency.path && dependency.resources) {
// run over resources array of each dependency
for (let n = 0; n < dependency.resources.length; n++) {
let resource = dependency.resources[n];
let ext = resource.substr(resource.lastIndexOf('.') + 1);
// only copy resources that are not managed by aurelia-cli
if (ext !== 'js' && ext != 'css' && ext != 'html' && ext !== 'less' && ext != 'scss') {
collectedResources.push(resource);
dependency.resources.splice(n, 1);
n--;
}
}
if (collectedResources.length) {
if (gitignore.indexOf(dependency.name)< 0) {
console.log('Adding line to .gitignore:', dependency.name);
fs.appendFile('./.gitignore', os.EOL + dependency.name, (err) => { if (err) { console.log(err) } });
}
for (let m = 0; m < collectedResources.length; m++) {
let currentResource = collectedResources[m];
if (currentResource.charAt(0) != '/') {
currentResource = '/' + currentResource;
}
let path = dependency.path.replace("../", "./");
let sourceFile = path + currentResource;
let destPath = './' + dependency.name + currentResource.slice(0, currentResource.lastIndexOf('/'));
console.log('Copying resource', sourceFile, 'to', destPath);
// copy files
gulp.src(sourceFile)
.pipe(gulp.dest(destPath));
}
}
}
}
}
function readProjectConfiguration() {
return build.src(project);
}
function writeBundles() {
return build.dest();
}
Updated aurelia.json
{
"name": "font-awesome",
"main":"",
"path": "../node_modules/font-awesome",
"resources": [
"css/font-awesome.css",
"/fonts/fontawesome-webfont.woff2",
"/fonts/FontAwesome.otf",
"/fonts/fontawesome-webfont.eot",
"/fonts/fontawesome-webfont.svg",
"/fonts/fontawesome-webfont.ttf"
]
}
Included font-awesome in html
<require from="font-awesome/css/font-awesome.css"></require>
Error:
get:
http://localhost:9000/font-awesome/fonts/fontawesome-webfont.woff2?v=4.7.0
(same with woff and ttf)
It's really strange because the files are copied and the url is correct..
Folder structure:
Tested a couple of different sources
What am I missing?
I would prefer a less implementation so I can import Font-Awesome in my master less file.
Based off of the discussion, since you are hosting your project inside the wwwroot folder, you must base your "gets" for files from there.
So, if you move your font files into wwwroot/fonts/font-name.woff (or somewhere thereabouts), you should be golden.
If you are on a webpack based project generated with latest (2019ish) aurelia cli , then adding fontawesome or bootstrap is pretty simple.
step 1: install fontawesome
check the official docs here. Just for completeness, here is the npm or yarn way for free version
//with npm
npm install --save-dev #fortawesome/fontawesome-free
// yarn
yarn add --dev #fortawesome/fontawesome-free
step 2: import the font
in your main.js or main.ts or app.js or app.ts , all of them will work equally well, which is better? ask google.
import '#fortawesome/fontawesome-free/css/all.min.css';
And an even simpler method would be to add the CDN version into the head of your index.esj or index.html file
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.1/css/all.css" />
all of the above work equally well, personally for public apps, I prefer CDN solution due to browser cache.