diff --git a/.gitignore b/.gitignore index 5b7db5a..e4cb999 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ /assets /articulos/cached/* .DS_Store +.vscode/ # Do not ignore these files... !/articulos/cached/.htaccess diff --git a/.htaccess b/.htaccess index 74d303b..310824a 100644 --- a/.htaccess +++ b/.htaccess @@ -176,22 +176,22 @@ AddType text/x-vcard vcf # HTML, TXT, CSS, JavaScript, JSON, XML, HTC: FilterDeclare COMPRESS - FilterProvider COMPRESS DEFLATE resp=Content-Type $text/html - FilterProvider COMPRESS DEFLATE resp=Content-Type $text/css - FilterProvider COMPRESS DEFLATE resp=Content-Type $text/plain - FilterProvider COMPRESS DEFLATE resp=Content-Type $text/xml - FilterProvider COMPRESS DEFLATE resp=Content-Type $text/x-component - FilterProvider COMPRESS DEFLATE resp=Content-Type $application/javascript - FilterProvider COMPRESS DEFLATE resp=Content-Type $application/json - FilterProvider COMPRESS DEFLATE resp=Content-Type $application/xml - FilterProvider COMPRESS DEFLATE resp=Content-Type $application/xhtml+xml - FilterProvider COMPRESS DEFLATE resp=Content-Type $application/rss+xml - FilterProvider COMPRESS DEFLATE resp=Content-Type $application/atom+xml - FilterProvider COMPRESS DEFLATE resp=Content-Type $application/vnd.ms-fontobject - FilterProvider COMPRESS DEFLATE resp=Content-Type $image/svg+xml - FilterProvider COMPRESS DEFLATE resp=Content-Type $image/x-icon - FilterProvider COMPRESS DEFLATE resp=Content-Type $application/x-font-ttf - FilterProvider COMPRESS DEFLATE resp=Content-Type $font/opentype + FilterProvider COMPRESS DEFLATE "%{Content_Type} = 'text/html'" + FilterProvider COMPRESS DEFLATE "%{Content_Type} = 'text/css'" + FilterProvider COMPRESS DEFLATE "%{Content_Type} = 'text/plain'" + FilterProvider COMPRESS DEFLATE "%{Content_Type} = 'text/xml'" + FilterProvider COMPRESS DEFLATE "%{Content_Type} = 'text/x-component'" + FilterProvider COMPRESS DEFLATE "%{Content_Type} = 'application/javascript'" + FilterProvider COMPRESS DEFLATE "%{Content_Type} = 'application/json'" + FilterProvider COMPRESS DEFLATE "%{Content_Type} = 'application/xml'" + FilterProvider COMPRESS DEFLATE "%{Content_Type} = 'application/xhtml+xml'" + FilterProvider COMPRESS DEFLATE "%{Content_Type} = 'application/rss+xml'" + FilterProvider COMPRESS DEFLATE "%{Content_Type} = 'application/atom+xml'" + FilterProvider COMPRESS DEFLATE "%{Content_Type} = 'application/vnd.ms-fontobject'" + FilterProvider COMPRESS DEFLATE "%{Content_Type} = 'image/svg+xml'" + FilterProvider COMPRESS DEFLATE "%{Content_Type} = 'image/x-icon'" + FilterProvider COMPRESS DEFLATE "%{Content_Type} = 'application/x-font-ttf'" + FilterProvider COMPRESS DEFLATE "%{Content_Type} = 'font/opentype'" FilterChain COMPRESS FilterProtocol COMPRESS DEFLATE change=yes;byteranges=no @@ -355,11 +355,11 @@ FileETag None # Option 1: # Rewrite "www.example.com -> example.com" - - RewriteCond %{HTTPS} !=on - RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] - RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L] - +# +# RewriteCond %{HTTPS} !=on +# RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] +# RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L] +# # ---------------------------------------------------------------------- @@ -374,7 +374,12 @@ FileETag None # RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L] # - +# Add HTTPS to HTTP requests + +RewriteEngine On +RewriteCond %{HTTPS} off +RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] + # ---------------------------------------------------------------------- # Built-in filename-based cache busting diff --git a/README.md b/README.md new file mode 100644 index 0000000..d0884c0 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# codeBlog +Blog de Médula diseño sobre código + +Semi-static generator written in PHP. diff --git a/SlypCore.php b/SlypCore.php index 0d35ff1..5d51dfd 100644 --- a/SlypCore.php +++ b/SlypCore.php @@ -303,6 +303,7 @@ public function newArticle( $filename ){ $toSave='title:' . $theTitle . "\n"; $toSave.='subtitle:' . "\n"; $toSave.='classes: language-markup' . "\n"; + $toSave.='draft: true' . "\n"; $toSave.="\n\n"; $toSave.='
diff --git a/article.php b/article.php index 95fe04d..519f963 100644 --- a/article.php +++ b/article.php @@ -2,19 +2,7 @@ $documentLang = 'en'; if(isset($theArticle->lang) && $theArticle->lang)$documentLang = $theArticle->lang; ?> - - - - - @@ -29,6 +17,8 @@ "> + + @@ -74,15 +64,15 @@ /* * * DON'T EDIT BELOW THIS LINE * * */ (function() { var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; - dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js'; + dsq.src = 'https://' + disqus_shortname + '.disqus.com/embed.js'; (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); })(); - + comments powered by Disqus @@ -100,8 +90,6 @@ - - diff --git a/articulos/Check-if-folder-exists-in-nodejs.textile b/articulos/Check-if-folder-exists-in-nodejs.textile new file mode 100644 index 0000000..0504a27 --- /dev/null +++ b/articulos/Check-if-folder-exists-in-nodejs.textile @@ -0,0 +1,159 @@ +title: Nodejs v10 fsPromises: Let's check if a dir exists, the modern way. +subtitle:In nodejs you sometimes need to check if a given path is an actual folder or not, since node 10, you can do it with promises, along with a lot of other file system operations. +classes:language-javascript +pubDate:2018-07-11T15:35:40-07:00 + +
+ +h1. Check if folder exists in node, asynchronously with promises, native. + +h2. Not only that, pretty much all fs methods are available with a promises interface. +
+ +p(intro). Since Node v10.0.0 fs has experimental promises support, to test that, we want to see if a folder exists and is accessible. Wi will start from the Synchronous operation, and we will end up taking advantage of @async await@ to deal with the promises. Only one thing to note: this is flagged as experimental, and we will get something like: @(node:578) ExperimentalWarning: The fs.promises API is experimental@ . + +h2. The setup + +We will use the @fs.stat@ method, in all it's different flavours if the path does not exist or is not accessible, you get an error: @ENOENT@. Also make sure your environment is running on node v10 or older. **v10 goes LTS in just a few months**, and in node v10 you can use @fs@ with promises. + +First let's make the directory and file structure we will test. + +bc. mkdir -p uploads/memes +echo "some content for the file">uploads/memes/not-folder +touch stat.js + +Open @stat.js@ and import right away both versions of @fs@. Also set the paths to be tested, we want to check the following 3 cases: + +* 1. A valid directory +* 2. A folder does not exist (fs.stat should throw an error) +* 3. A file; path resolves to something but it is not a dir + +bc.. const fs = require("fs"); +const fsPromises = require("fs").promises; + +const pathsToTest = [ + "uploads/memes", + "nopes/memes", + "uploads/memes/not-folder", +]; + +function isErrorNotFound(err) { + return err.code === "ENOENT"; +} + +p. Also we will define an **error checker function** that will be reused by all the methods we build. + +Before we start with the actual methods we will setup **looping functions** that will pick up the array of paths and ask the given method if each of the paths is a directory, then **print the method used and the result**. For each fs.stat variation we will use a slightly different looper, but the principle stands. + +h2. The simple way: fs.statSync + +bc.. function isFolder_sync(path) { + try { + const stat = fs.statSync(path); + return stat.isDirectory(); + } catch (err) { + // if it's simply a not found error + if (isErrorNotFound(err)) { + return false; + } + //otherwise throw the error + throw err; + } +} + +/** Looper function */ +function checkPathsSync(method) { + console.log(`${method.name}: `, ...pathsToTest.map(path => method(path))); +} + +checkPathsSync(isFolder_sync); +//isFolder_sync: true false false + +p. The core idea is: we call @fs.statSync@ inside a @try catch@ block to handle the case where the dir is not found, if the error is something else we don't recognize, we still throw. + +h2. The classic Node: fs.stat (with a callback) + +bc.. function isFolder_callback(path, callback) { + fs.stat(path, (err, stat) => { + if (err) { + const errorToReturn = isErrorNotFound(err) ? undefined : err; + callback(errorToReturn, false); + return; + } + callback(undefined, stat.isDirectory()); + }); +} + +function checkPaths(method) { + pathsToTest.forEach(path => + method(path, (err, result) => + console.log(`${method.name}: `, err ? err : result) + ) + ); +} + +checkPaths(isFolder_callback); +// isFolder_callback: true +// isFolder_callback: false +// isFolder_callback: false + +p. Callbacks will catch errors, so no need for the try catch. Personally I find Callbacks very pretty in simple use cases. + +h2. The new approach: promises enabled fs.stat + +bc.. function isFolder_promise(path) { + return fsPromises + .stat(path) + .then(fsStat => { + return fsStat.isDirectory(); + }) + .catch(err => { + if (isErrorNotFound(err)) { + return false; + } + throw err; + }); +} + +function checkPromisedPaths(method) { + Promise.all(pathsToTest.map(path => method(path))).then(values => { + console.log(`${method.name}: `, values); + }); +} + +checkPromisedPaths(isFolder_promise); +// (node:877) ExperimentalWarning: The fs.promises API is experimental +// isFolder_promise: [ true, false, false ] + +p. Same idea as before, catch the not found error, if anything else is caught, throw a fuss with the error. + +h2. To wrap up: Async Await. + +h4. beacause, why not? + +bc.. async function isFolder_asyncAwait(path) { + // the result can be either false (from the caught error) or it can be an fs.stats object + const result = await fsPromises.stat(path).catch(err => { + if (isErrorNotFound(err)) { + return false; + } + throw err; + }); + + return !result ? result : result.isDirectory(); +} + +checkPromisedPaths(isFolder_asyncAwait); +// isFolder_asyncAwait: [ true, false, false ] + +p. This was a fun actual implementation of @async await@, I had not used it so far, beyond the typical hello world. + +h3. What can be improved? + +well, the @isErrorNotFound@ method should be taking care of @throw@ing a fit if the path is not finding anything. Also I'm sure I can come up with more elegant versions of the implementations, but I'm happy with this as a POC. + +The whole code can be found as a gist at: "$":https://gist.github.com/baamenabar/d639055caaacd5dbd139c302caf8a4f9 + +h2. Resources + +Main resource is the node docs: "$":https://nodejs.org/api/fs.html#fs_fs_promises_api ...aaand of course "MDN":https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function. diff --git a/articulos/Conflicting-IPs-with-docker-machine.textile b/articulos/Conflicting-IPs-with-docker-machine.textile new file mode 100644 index 0000000..371c7bb --- /dev/null +++ b/articulos/Conflicting-IPs-with-docker-machine.textile @@ -0,0 +1,19 @@ +title:Conflicting IPs with docker machine +subtitle:Short tip for debugging +classes: language-markup +pubDate:2017-01-18T07:24:13-01:00 + + +h1. Conflicting IPs with docker machine + +p(intro). If you are using multiple machines with docker-machine they will get an automatic IP starting from 192.168.99.100 , then 192.168.99.101 and so on. The problem comes when you restart your system and start the machines in different order. Virtualbox will assign different IPs this time around, this makes the certificates invalid and you need to regenerate them. No problem there, but if you have mapped an IP to a domain in your hosts file, then trouble begins. + +You can’t really control which IP virtualbox will assign to the machine; see https://github.com/docker/machine/issues/1709 . So you can not assign a specific IP to a docker-machine virtualbox vm. + +But you can give it a range and assume it will fall in the 192.168.x.100 pattern. Use the following command when creating. + +bc. docker-machine create -d virtualbox --virtualbox-hostonly-cidr "192.168.98.1/24" victor + +So when you restart your computer, they will respect the range and usually will fall in the .100 IP + +Also consider other workarounds presented in that thread, like this script: https://github.com/fivestars/docker-machine-ipconfig diff --git a/articulos/Force-a-file-download-from-the-browser-with-Blob.textile b/articulos/Force-a-file-download-from-the-browser-with-Blob.textile new file mode 100644 index 0000000..d065261 --- /dev/null +++ b/articulos/Force-a-file-download-from-the-browser-with-Blob.textile @@ -0,0 +1,69 @@ +title:Force a file download from the browser with Blob +subtitle:The browser will always try to read data you give it. +classes: language-markup +pubDate:2018-02-13T12:33:23-01:00 + + +
+ +h1. Force a file download from the browser with Blob + +h2. The browser will always try to read data you give it. +
+ + +p(intro). You have a bunch of data you just generated in JavaScrip and you want to force the user to download it as a file. How to do it? + +h2(#ac2). TL;DR: + +p. From small to medium files (something that fits in your RAM) take advantage of the data URI of elements. And this is how the spec expects it to be handled. +https://www.w3.org/TR/FileAPI/#requirements + +bc. download + +So for an existing anchor element with a class js-download-button we would do something like the following: + +h3. DOM naive approach: + +just create an anchor element and put the data in the href attribute. +https://ourcodeworld.com/articles/read/189/how-to-create-a-file-and-generate-a-download-with-javascript-in-the-browser-without-a-server + +bc. const downloadButton = document.querySelector('.js-download-button'); +downloadButton.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent({sone: 'object', with: 'data'})); +downloadButton.setAttribute('download', ‘myJsonFileName.JSON'); + +h3. JS approach: + +Take advantage of the .createObjectURL(blob) method and the Blob API. MDN has a good example on this approach. +https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications#Example_Using_object_URLs_to_display_images + +**note that:** Each time you call createObjectURL(), a new object URL is created, even if you've already created one for the same object. Each of these must be released by calling URL.revokeObjectURL() when you no longer need them. Browsers will release these automatically when the document is unloaded; however, for optimal performance and memory usage, if there are safe times when you can explicitly unload them, you should do so. () +(from https://stackoverflow.com/a/33542499/537314 ) + +it would look like this: + +bc.. let contentBlob; + +function saveAsJson(fileName, data) { + jsonString = JSON.stringify(data, null, 2); + + // resetting if you do this more than once, or you'll get a memory leak + if (contentBlob) { + window.URL.revokeObjectURL(contentBlob); + contentBlob = undefined; + } + + // populate the download button + const downloadButton = document.querySelector('.js-download-button'); + contentBlob = new Blob([jsonString], {type : 'application/json'}); + downloadButton.href = window.URL.createObjectURL(contentBlob); + downloadButton.download = fileName + (new Date().getTime()) + '.JSON'; +} + +saveAsJson('FILE-NAME-', {sone: 'object', with: 'data'}); + + +p. But if you want the foolproof, all cases handled version use the FileSave.js lib. +https://github.com/eligrey/FileSaver.js/blob/master/src/FileSaver.js + +If you have huge files, you are probably doing it wrong, but take a look at the Streams API, and this library: ( https://github.com/jimmywarting/StreamSaver.js ). diff --git a/articulos/Getting-file-md5-checksums-in-different-OSs.textile b/articulos/Getting-file-md5-checksums-in-different-OSs.textile new file mode 100644 index 0000000..2d7dcbd --- /dev/null +++ b/articulos/Getting-file-md5-checksums-in-different-OSs.textile @@ -0,0 +1,97 @@ +title:Getting file md5 checksums in different OSs +subtitle:Generating md5 file checksums vary from one OS to another, and because I like developing in varying environments, I need solid equivalences. +classes: language-markup +pubDate:2017-05-08T08:14:05-02:00 + + +
+ +h1. Getting file md5 checksums in different OSs + +h2. Generating md5 file checksums vary from one OS to another, and because I like developing in varying environments, I need solid equivalences. +
+ + +p(intro). For cache breaking I like to use MD5 hashes of files. At the Westwing magazine we had some javascript bundles that we change very seldomly, so a timestamp on each build is too aggressive cache break. We also use file checksums for font bundles. + +For this we have a bash script that will create the hash from the bundled files, so, if nothing has changes, we avoid unnecessary requests to our users. + +We used to have the projects inside Vagrant Boxes, so all scripts run in linux environment, no problem. But as we moved to Docker (we love it) and we do frontend development directly on our machines, some things changed. For instance the md5sum function, in mac OSX it's called just md5 and the output is slightly different. Because of the output an alias for md5sum will not work. + +bc(language-sh). # Linux +md5sum Gruntfile.js +7593278019c7726f7271904cd7dda73a Gruntfile.js +# mac OSX +bc. md5sum Gruntfile.js +MD5 (Gruntfile.js) = 7593278019c7726f7271904cd7dda73a +# win 10 with Cmder +md5sum Gruntfile.js +7593278019c7726f7271904cd7dda73a *Gruntfile.js + + +To deal with this we need 3 things: +1. Check the OS is mac +2. Filter out the hash from the output +3. Store on a variable + +To figure out which system the script is running into we can use @uname@, and with that we can choose syntax. For detecting OS I found the "following script in Stack Overflow":http://stackoverflow.com/questions/3466166/how-to-check-if-running-in-cygwin-mac-or-linux#answer-17072017 + +bc.. #!/usr/bin/env bash +ENVIRONMENT = "unknown" +if [ "$(uname)" == "Darwin" ]; then + # Do something under Mac OS X platform + ENVIRONMENT = "mac" +elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then + # Do something under GNU/Linux platform + ENVIRONMENT = "linux" +elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then + # Do something under Windows NT platform + ENVIRONMENT = "win" +fi + +p. To get the hash we can use regex with @sed@, or even simpler, we use @cut@, which is a little like @String.prototype.split()@ in JS or @explode()@ in PHP, it. The main important difference, is the delimiter is only one byte character (ASCII only) and it returns a list of fields, not an array, but you can access it's elements with -f using 1 based index. It is not an array but for this it helps to see it that way. + +To get just @md5sum@ we pipe (@ | @) the output to @cut@ , split on a space character and get the first field. + +bc. md5sum Gruntfile.js | cut -d ' ' -f 1 + +to store this in a var we to do a "Command Substitution":https://www.gnu.org/software/bash/manual/bashref.html#Command-Substitution so the output can be stored on a variable. + +bc. GRUNTHASH=$( md5sum Gruntfile.js | cut -d ' ' -f 1 ) + +Will output: @7593278019c7726f7271904cd7dda73a@ + +h2. Storing the hash + +Finally we can store it to a file as a constant. + +bc. echo "" > app/path/hashes.php; + +h2. Putting it all together + +We can build a simple function for hashing. + +bc.. #!/bin/bash + +get_md5_checksum () { + if [ "$(uname)" == "Darwin" ]; then + THEHASH=($(md5 $1 | cut -d= -f2 | cut -d " " -f2)) + else + THEHASH=($(md5sum $1 | cut -d ' ' -f 1)) + fi +} + +get_md5_checksum Gruntfile.js +echo $THEHASH + +p. This will output the hash of the file either on mac, or linux. + +h2. Epilogue + +This seemingly simple task taught me a whole bunch of things about bash and bash scripts. I feel way more powerful now with this new set of tools. + +h3. How to md5 a file in PowerShell ? + +bc. Get-FileHash -Algorithm MD5 + +Yeah, you can add that to the mix, if you are up to the task. diff --git a/articulos/Jasmine-unit-testing-primer-in-Angular.textile b/articulos/Jasmine-unit-testing-primer-in-Angular.textile new file mode 100644 index 0000000..70a3059 --- /dev/null +++ b/articulos/Jasmine-unit-testing-primer-in-Angular.textile @@ -0,0 +1,107 @@ +title: Karma + Jasmine unit testing components in Angular 2+ +classes: language-javascript +startDate:2018-04-25T20:11:03+02:00 +pubDate:2019-01-14T23:10:40+02:00 + +h1. Karma / Jasmine (unit) Tests for components in an Angular project + +h2. Part 2 of the Testing Angular series: The basics of testing components. + +p. Testing services is fairly straightforward, you can treat them as regular classes with methods in there. For testing Components requires us to make draw a line, do we want to check just functions in the component? or do we want to check the component working to do what it is intended do do? this is where some people make the difference between unit and integration tests. Here we will bundle them together as unit, a unit of functionality called component. There will be plenty of space for e2e tests in a later post. + +h2. Make the component render (not crash) + +Ugly as that may sound, that is your first step. All component tests start with just trying to instantiate the component in a dummy app, this is all handled by TestBed, an Angular specific testing utility library. + +Because the component is isolated, all it usually is imported and declared in the Module, **during testing, these dependencies are not automatically available to the component**, so you have to declare them manually. Let's look at this sample component. + +bc.. // sample.component.ts +import { Component, OnInit } from '@angular/core'; +import { ThingsService } from '../service/things.service'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Observable } from 'rxjs'; + +@Component({ + selector: 'app-sample', + templateUrl: './sample.component.html', +}) +export class SampleComponent implements OnInit { + constructor(private thingsService: ThingsService, private router: Router, private route: ActivatedRoute) {} + + listOfThings$: Observable; + + ngOnInit(): void { + this.route.url.subscribe(segments => { + this.listOfThings$ = this.thingsService.getThings(segments); + }); + } + + actionButtonClicked(): void { + this.thingsService.doAction(); + } +} + +bc(language-makrup). // sample.component.html + + + Logo + + + + + +And the imports in the spec file look like this: + +bc. // sample.component.spec.ts +beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ + SampleComponent, // this is the component itself + ThingsListComponent, // this is the component instantiated in the template + ], + providers: [ + ThingsService // the service passed in the constructor + ], + imports: [ + MatToolbarModule, // this is one of the custom mat-* elements seen in the template + RouterTestingModule, // this loads the Router and the ActivatedRoute "services" + HttpClientModule, // this is actually a dependency of the ThingsService (this will bite you often) + ], + }).compileComponents(); +})); + +For the dependencies you need to pay attention in 3 places: + +1. The Component Class @sample.component.ts@ +2. The Component Template @sample.component.html@ +3. The Module where the component is declared (maybe) + +h3. Component Class + +The first part where to look for dependencies is the **constructor**, here services get injected. Most of the services you create need to be passed in the providers. But they have their own dependencies. So, as a general recommendation, unless the service is trivial, **mock all services that a component needs**. But for now let's also look into the service dependencies and add them to the @providers@ or @imports@ arrays. + +h3. Component Template + +By looking at the template you have to quickly figure out if your component is instantiating **child components**, or directives within. In out case we have @@ which can either come from an external module or from this same module, if it's in this same module it has to be declared in the @declarations@ array. + +If it is an external module (from this same app or from a package) like @@ and @@, we need to import it in the @imports@ array. + +h3. Component's Module + +If you make small modules per each piece of functionality, going to the module where the component is declared and check the imports, you can probably figure out any missing import. + +As a quick tip, some modules and services have a testing version like the @RouterModule@ has @RouterTestingModule@, which actually prevents the need to mock the router. + +h2. Initial state for @Input() + +As a warning, some components have @Input() vars, and the business logic expect them to be populated, but when testing, no component is passing in any values, breaking the test (sometimes with unclear messages). If you have any input you have three options: + +1. Have the component be instantiated by a testing wrapper component (the nice solution) which can pass different inputs to test different use cases. +2. Pass the value of the @@input@ to the instantiated component before any logic happens, removing anything related to the input from the constructor. +3. Make some default value for all the inputs in your component. + +Option 2 and 3 are not very recommended, because you should not code your application to fix your tests, only to be testable. + +h2. Outro + +There is a lot more to cover about testing components in Angular. This is to get familiar with loading the component dependencies. diff --git a/articulos/Karma-unit-tests-basic-config-for-an-Angular-CLI-project-in-Linux-with-Chrome.textile b/articulos/Karma-unit-tests-basic-config-for-an-Angular-CLI-project-in-Linux-with-Chrome.textile new file mode 100644 index 0000000..5fe3258 --- /dev/null +++ b/articulos/Karma-unit-tests-basic-config-for-an-Angular-CLI-project-in-Linux-with-Chrome.textile @@ -0,0 +1,113 @@ +title: Setting up Karma tests for an Angular CLI project. +classes: language-markup +startDate:2018-04-25T20:11:03+02:00 +pubDate:2018-12-27T14:35:40-08:00 + +h1. Karma (unit) Tests for an Angular CLI project aimed at CI + +h2. Part 1 of the Testing Angular series: How to configure the Jasmine Unit tests run by Karma. + +p. With the final goal of having a CI pipeline building and testing an Angular project. We begin with troubleshooting for running an Angular CLI project karma-jasmine tests in Linux environments, including WLS. + +h2. What do we want from our unit tests? + +The barest of the barest is code coverage with tests. Ideally your unit tests cover more than just branches, but just by having close to 100% coverage your code will be better. + +We need reporting, for us, and later for our pipeline. + +We need to decide in a testing environment: a Browser, a Headless Browser, or virtual dom. I really really like the purity of not touching a browser to run the **unit** tests. The default uses Chrome (which is not easy to install on Linux environments), so we'll stick to that, but later I will explore switching to "jsdom":https://www.npmjs.com/package/karma-jsdom-launcher or even Jest. + +h3. What are unit tests in Angular? + +... not going there ... I've seen many kinds. It is up to you. + +h2. Configuration + +Most of the config is done in @src/karma.conf.js@ and this will be loaded by the @ng test@ command. + +In theory you can run Angular tests directly using karma, but in practice you will have more trouble and misconfigurations than anything. The command @ng test@ can forward some flags to karma, but not all and it will not overwrite many configs in the @src/karma.conf.js@. You can even have custom flags, since the config is a @.js@ file that will be run on node, so you can capture the params passed to it. + +The dafault file has Chrome as the target browser which works fine if you ar running on a Windows or Mac env, but on linux you most likely have Chromium, on WSL it is the same. + +h3. Installing Chrome to run it Headless (in Linux): + +On the Windows Linux Subsystem you can install chrome directly from google. + +To install follow the instructions layed out here: https://askubuntu.com/a/79284/469134 + +bc. sudo apt-get install libxss1 libappindicator1 libindicator7 +wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb +sudo dpkg -i google-chrome*.deb + +if dpkg fails run the following: + +bc. sudo apt-get install -f + +After that run @google-chrome --version@ to confirm it´s available. Then just run @google-chrome@. + +h4. Troubleshooting: + +The first error you will get by trying to run chrome might be something like: + +bc. [3333:3333:1234/567890.123456:ERROR:browser_dm_token_storage_linux.cc(93)] Error: /etc/machine-id contains 0 characters (32 were expected). + +or + +bc. [3333:3333:1234/567890.123456:ERROR:browser_dm_token_storage_linux.cc(93)] Error: /etc/machine-id contains 32 characters (32 were expected). + +I have read this is not supposed to happen, and should not be required by the browser, but it is, even by version 71, my guess is it?s trying to get show something on screen or something of that sort, because if you run. + +bc. google-chrome --headless + +The error goes away, but now you get something like: + +bc. [1227/230724.702337:ERROR:gpu_process_transport_factory.cc(967)] Lost UI shared context. + +Which apparently means too many possible things. So copying and pasting around flags what works at the end of 2018 is: + +bc. google-chrome --headless --disable-gpu --no-sandbox --remote-debugging-port=9222 + +This means we need to update the @src/karma.conf.js@ and tell it to use a custom launcher, in our case a custom configuration for the Chrome Launcher. First we rename the browser sring to something we understand + +bc(language-javascript). browsers: ['Chrome'], + +to + +bc(language-javascript). browsers: ['ChromeHeadless'], // or MyChromeHeadlessConfiguration if you want + +Then you need to add the customLaunchers (just below browsers is fine) + +bc(language-javascript). +browsers: ['ChromeHeadless'], + customLaunchers: { + ChromeHeadless: { + base: 'Chrome', + displayName: 'Chrome (headless)', + flags: [ + '--headless', + '--disable-gpu', + '--no-sandbox', + '--remote-debugging-port=9222', + ] + } + } + +h2. Code coverage + +The defaults for now are fine, I just like to add @text-summary@ to the lists of reporters. So my istambul reporter config looks like this. + +bc(language-javascript). coverageIstanbulReporter: { + dir: require('path').join(__dirname, '../coverage'), + reports: ['html', 'lcovonly', 'text-summary'], + fixWebpackSourcePaths: true, +}, + +Some things you don´t have to test, like mocks, to prevent them from ruining your coverage use: + +bc. /* istanbul ignore next */ + +for istambul to ignore the next line + +h2. Wrapping up + +Now just run your tests @ng test --code-coverage@. diff --git a/articulos/Passing-arguments-from-the-console-to-Gulp.textile b/articulos/Passing-arguments-from-the-console-to-Gulp.textile new file mode 100644 index 0000000..cc32a82 --- /dev/null +++ b/articulos/Passing-arguments-from-the-console-to-Gulp.textile @@ -0,0 +1,39 @@ +title:Passing arguments from the console to Gulp +subtitle:In node scripts (like Gulp) you sometimes need to pass arguments, here is how. +classes: language-markup +pubDate:2016-04-16T19:35:20+01:00 + + +h1. Passing arguments from the console to Gulp + +h2(subtitle). Node scripts you need to pass arguments, getting them can be cumbersome. + +p(intro). If you want to run a task with certain parts turned **off** or **on**, or even pass a value from the command line to gulp, by default you can’t. Well you can, but it’s a node thing: @process.argv@ it is just an array, so it's a bit limited, so there is a module to abstract the mess: "yargs":https://www.npmjs.com/package/yargs . + +bc. npm install —save-dev yargs + +Then you require it. + +bc(language-javascript). var argv = require('yargs').argv; + +Now you have access to the arguments or flags passes from the console. Something like: + +bc. gulp css —verbose + +will be available in the gulpfile as @argv.verbose@, or + +bc. gulp html —lang=es + +will be reachable in the gulpfile with @argv.lang@ and you’ll get the string. + +h2. no dependencies option + +For simple flags that are either there or not you can just filter for them, without the need to install a package. + +bc. gulp css --no-minification + +can be checked inthe script as follows + +bc(language-javascript). const = noMinification = process.argv.filter(item => item === 'no-minification'); + +...and that's all, it does not scale well for more configuration flags, and options, but is cleaner than adding a dependency. diff --git a/articulos/Quick-development-setup-for-Windows-Linux-Subsystem-with-oh-my-zsh.md b/articulos/Quick-development-setup-for-Windows-Linux-Subsystem-with-oh-my-zsh.md new file mode 100644 index 0000000..f7d05e1 --- /dev/null +++ b/articulos/Quick-development-setup-for-Windows-Linux-Subsystem-with-oh-my-zsh.md @@ -0,0 +1,219 @@ +title:Quick development setup for Windows Linux Subsystem with oh-my-zsh +subtitle:How to set up a Windows 10 development environment for web apps with a capable, friendly terminal and nodejs. +classes: language-markup +pubDate:2018-03-18T21:18:17-01:00 +draft:true +markdown:true + + +# Quick development setup for Windows Linux Subsystem with oh-my-zsh + +After 3 years working on a mac and a Windows machines separately (mostly on the mac). I recently fully switched to Windows and found myself with a few days to setup my development environment. + +The time has come, where Windows 10 software ecosystem has reached a point where I can setup my development environment and claim the following: + +### I like my dev environment more on windows than on the mac. + +Now on how to set up a Windows 10 development environment for web apps with a capable, friendly terminal (I really liked iTerm2 on mac). + +## Overview of the steps + +- Update windows +- Activate the Window Linus Subsystem +- Install Sublime (or any editor you like) +- Install chocolatey +- Install cmder and git +- Install Ubuntu +- Install pull your dotfiles +- Install zsh and oh-my-zsh +- Install the themes and colorschemes +- Generate your ssh keys, and add them to your windows. +- Install nvm + +## 1. Update your windows to the latest version +I will not explain that + +## 2. Activate the Window Linuxs Subsystem +First Open PowerShell ISE (as Administrator), which is quite nice I might say, it reconizes stuff like `pwd` or `ls` and has an interesting command completion. + +Then activate the Window Linux Subsystem (WSL) from the terminal with the follwing command. +```sh +Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux +``` +You will be prompted to restart your machine. +I learnt that the term "elevated prompt" or "elevated something" is refered to a program running as an Administrator (right click-> run as Administrator). + +## 3. Install Cocolatey +It's like Brew, but for windows, and just like brew, it does not solve all, but it works for a lot of stuff. +Go to https://chocolatey.org/install and follow the instructions. +Close and re-open your PowerShell (As admin). +Run the following command to allow chocolatey to make a confirmation prompt when installing stuff. + +```sh +choco feature enable -n allowGlobalConfirmation +``` + +## 4. Install cmder +Cmder is a very nice, fast and complete terminal for windows, from which you can spin pretty much any command line available in windows. + +From an "elevated command shell" (running as admin), use chocolatey to get cmder + git version. Instructions are at: http://cmder.net/ but basically just run the following from your powerShell: + +```sh +choco install cmder +``` + +This will also install git for you. Open cmder by searching it in the windows menu, or by closing and opening your terminal and running `cmder` and check how is it working for you. + +## Install Ubuntu fom the windows store +Simple as that, search for Ubuntu in the Windows store and install it. + +Open the bash terminal to your Ubuntu. It will make a bunch of updates the first time, then setup your user and password. + +Before anything else run `sudo apt-get update`. + +## Tangent: Open files with Sublime Text directly from the terminal +Either you are awesome at nano or vim from the box, or you will want to open files with your editor of choice from the command line. To do that, with Sublime, you have to add Sublime Text to your Path. + +* Hit `WIN` + `R`, type `SystemPropertiesAdvanced` and hit Enter. +* Select the button **Environment variables**. +* Select `path` in the list from the top and push the **Edit** button. +* Click **Add**, then click **Browse**... +* Navigate where your Sublime Text is installed, the path added should look similar to this: `C:\Program Files\Sublime Text 3` + +Now on any console you can use `subl some-file.js` and sublime will open it. + +## Add your dotfiles +Since we probably have not yet generated any ssh keys, we just need to pull the repo via `https` (without authentication). + +To test that everything is running smoothly, close all conseles, then open cmder, then type `bash`, enter, then the console would be bash inside the WSL. + +```bash +mkdir projects +cd projects +git clone https://github.com/baamenabar/dotfiles.git +``` + +This will create the folderl and pull the files in both linux and windows, since windows folder is "mounted". + +``` +vim .gitconfig +``` + +We edit the .gitconfig to our pleasing then we copy it to the user's folder. + +``` +cp .gitconfig ~/.gitconfig +``` + +Then we logout (`ctrl` + `d`) and we can use the same config in the windows environment, using the same command. Then we check the config. + +``` +cp .gitconfig ~/.gitconfig +git config -l --show-origin +``` + +The other files you can add in a simmilar way, but first, let's add zsh and oh-my-zsh extensions. + +## Installing zsh and oh-my-zsh + +Pretty straightforward, just follow any tutorial on the web that does this on linux. + +The only catch is to make it the default loaded shell and not bash, we only need to add the following inside the `~/.bashrc` file. + +``` +# Launch Zsh +if [ -t 1 ]; then +exec zsh +fi +``` + +Next time we start bash, it will actually be zsh (all credit to [Daniel Godigna](https://medium.com/@danielgodigna/how-to-install-zsh-oh-my-zsh-and-themes-in-ubuntu-on-windows-933489b6d6e0) for his article on Medium). + +Now for oh-my-zsh +``` +sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" +``` + +## Install the themes and colorschemes + +Install the Menlo for Powerline Font in your windows machine https://github.com/abertsch/Menlo-for-Powerline (It gives you awesome icons and a nice look for the _agnoster_ theme). + +Now config zsh to your taste `vim ~/.zshrc` I like adding a couple of aliases and small configs. + +``` +# show dots while searching auto complete +COMPLETION_WAITING_DOTS="true" + +# hide user from the prompt +DEFAULT_USER=`whoami` + +# personal preferences +# Super powerful customized ls alias +alias ll="ls -lhpA --time-style='+%Y-%m-%d %H:%M:%S' --group-directories-first" +``` + +Save and log out of zsh. You can now add the `ll` alias to cmder in windows itself. Just run the following without the ticks, it will be persisted in the config. + +``` +alias ll=ls -lhpA --time-style="+%Y-%m-%d %H:%M:%S" --group-directories-first +``` + +Now just add the ConEmu.xml coloschemes to the coloscheme section in the ` run as Administrator). + +h2. 3. Install Cocolatey + +It's like Brew, but for windows, and just like brew, it does not solve all, but it works for a lot of stuff. +Go to https://chocolatey.org/install and follow the instructions. +Close and re-open your PowerShell (As admin). +Run the following command to allow chocolatey to make a confirmation prompt when installing stuff. + +bc(language-sh). +choco feature enable -n allowGlobalConfirmation + + +h2. 4. Install cmder + +Cmder is a very nice, fast and complete terminal for windows, from which you can spin pretty much any command line available in windows. + +From an "elevated command shell" (running as admin), use chocolatey to get cmder + git version. Instructions are at: http://cmder.net/ but basically just run the following from your powerShell: + +bc(language-sh). +choco install cmder + + +This will also install git for you. Open cmder by searching it in the windows menu, or by closing and opening your terminal and running `cmder` and check how is it working for you. + +h2. Install Ubuntu fom the windows store + +Simple as that, search for Ubuntu in the Windows store and install it. + +Open the bash terminal to your Ubuntu. It will make a bunch of updates the first time, then setup your user and password. + +Before anything else run @sudo apt-get update@. + +h2. Tangent: Open files with Sublime Text directly from the terminal + +Either you are awesome at nano or vim from the box, or you will want to open files with your editor of choice from the command line. To do that, with Sublime, you have to add Sublime Text to your Path. + +* Hit @WIN@ + @R@, type @SystemPropertiesAdvanced@ and hit Enter. +* Select the button **Environment variables**. +* Select @path@ in the list from the top and push the **Edit** button. +* Click **Add**, then click **Browse**... +* Navigate where your Sublime Text is installed, the path added should look similar to this: @C:\Program Files\Sublime Text 3@ + +Now on any console you can use @subl some-file.js@ and sublime will open it. + +h2. Add your dotfiles + +Since we probably have not yet generated any ssh keys, we just need to pull the repo via `https` (without authentication). + +To test that everything is running smoothly, close all conseles, then open cmder, then type `bash`, enter, then the console would be bash inside the WSL. + +bc(language-sh). +mkdir projects +cd projects +git clone https://github.com/baamenabar/dotfiles.git + +This will create the folderl and pull the files in both linux and windows, since windows folder is "mounted". + +bc. vim .gitconfig + +We edit the .gitconfig to our pleasing then we copy it to the user's folder. + +bc. cp .gitconfig ~/.gitconfig + +Then we logout (@ctrl@ + @d@) and we can use the same config in the windows environment, using the same command. Then we check the config. + +bc. cp .gitconfig ~/.gitconfig +git config -l --show-origin + + +The other files you can add in a simmilar way, but first, let's add zsh and oh-my-zsh extensions. + +h2. Installing zsh and oh-my-zsh + +Pretty straightforward, just follow any tutorial on the web that does this on linux. + +The only catch is to make it the default loaded shell and not bash, we only need to add the following inside the @~/.bashrc@ file. + +bc. # Launch Zsh +if [ -t 1 ]; then +exec zsh +fi + +Next time we start bash, it will actually be zsh (all credit to [Daniel Godigna](https://medium.com/@danielgodigna/how-to-install-zsh-oh-my-zsh-and-themes-in-ubuntu-on-windows-933489b6d6e0) for his article on Medium). + +**EDIT:** as of late 2018 you don't need this workaround. You can invoque @wsl@ direcly from your Cmder terminal and it will load whatever you configure as your default shell. + +bc. chsh -s $(which zsh) + +More details at https://github.com/Microsoft/WSL/issues/1724#issuecomment-380155346 + +Now for oh-my-zsh + +bc. sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" + +h2. Install the themes and colorschemes + +Install the Menlo for Powerline Font in your windows machine https://github.com/abertsch/Menlo-for-Powerline (It gives you awesome icons and a nice look for the _agnoster_ theme). + +Now config zsh to your taste @vim ~/.zshrc@ I like adding a couple of aliases and small configs. + +bc.. +# show dots while searching auto complete +COMPLETION_WAITING_DOTS="true" + +# hide user from the prompt +DEFAULT_USER=`whoami` + +# personal preferences +# Super powerful customized ls alias +alias ll="ls -lhpA --time-style='+%Y-%m-%d %H:%M:%S' --group-directories-first" + +p. Save and log out of zsh. You can now add the @ll@ alias to cmder in windows itself. Just run the following without the ticks, it will be persisted in the config. + +bc. alias ll=ls -lhpA --time-style="+%Y-%m-%d %H:%M:%S" --group-directories-first + +Now just add the ConEmu.xml coloschemes to the coloscheme section in the @
+ +h1. SVG basic markup and syntax + +h2. I´m always trying to figure out the basic SVG markup. +
+ + +p(intro). I'm saving this here with the things I learn about SVGs. An SVG needs some basic markup, like the @@ tag, some other stuff is optional, depending on the use. + +bc. + + + + + home + + + + MDN Web Docs + + + +this is a simple version of the mozilla logo plus a symbol from an icon set. diff --git a/articulos/Setting-up-Prettier-as-External-tools-in-PhpStorm-on-windows-with-WSL.textile b/articulos/Setting-up-Prettier-as-External-tools-in-PhpStorm-on-windows-with-WSL.textile new file mode 100644 index 0000000..6a73c88 --- /dev/null +++ b/articulos/Setting-up-Prettier-as-External-tools-in-PhpStorm-on-windows-with-WSL.textile @@ -0,0 +1,31 @@ +title:Setting up Prettier as External tools in PhpStorm on windows with WSL +subtitle: +classes: language-markup +draft:true +pubDate:2018-03-15T20:22:42-01:00 + + +
+ +h1. Setting up Prettier as External tools in PhpStorm on windows with WSL + +h2. Subtitle +
+ + +p(intro). This is the intro that will be lloked up for the lead text of an article. + +h2(#ac2). __[fr]Mise en place__, first subtitle + +Here goes some text with a "link to this header":#ac2 followed by an image + +!img/content/file-structure-postcss-guide.png(This will be the alt text)! + +After the image, some code: + +bc(language-javascript). var someObject = { + part:true, + follow: "false" +}; + +And another paragraph diff --git a/articulos/Suddently-Virtual-Box-throws-network-error-on-Windows-10.textile b/articulos/Suddently-Virtual-Box-throws-network-error-on-Windows-10.textile new file mode 100644 index 0000000..501498b --- /dev/null +++ b/articulos/Suddently-Virtual-Box-throws-network-error-on-Windows-10.textile @@ -0,0 +1,29 @@ +title:Suddently Virtual Box throws network error on Windows 10 +classes: language-markup +pubDate:2017-08-17T22:20:44-02:00 + + +h1. Suddently Virtual Box throws network error on Windows 10 + +p(intro). I've been working with virtuabox on my Windows machine (Vagrant and Docker environments). +When I tried to start a machine (munich) I get a criptic network error. + +cb.. λ docker-machine start munich +Starting "munich"... +(munich) Check network to re-create if needed... +Unable to start the VM: C:\Program Files\Oracle\VirtualBox\VBoxManage.exe startvm munich --type headless failed: +VBoxManage.exe: error: Failed to open/create the internal network 'HostInterfaceNetworking-VirtualBox Host-Only Ethernet Adapter #6' (VERR_INTNET_FLT_IF_NOT_FOUND). +VBoxManage.exe: error: Failed to attach the network LUN (VERR_INTNET_FLT_IF_NOT_FOUND) +VBoxManage.exe: error: Details: code E_FAIL (0x80004005), component ConsoleWrap, interface IConsole + +Details: 00:00:01.748287 Power up failed (vrc=VERR_INTNET_FLT_IF_NOT_FOUND, rc=E_FAIL (0X80004005)) + +After much googling and reading, the solution is: + +Go to your *control panel* > *Network and shred resources center* > *Network connections* + +Here you will see a bunch of network connections icons. Amongst them: *VirtualBox Host-Only Network #6* + +Double click it and open it's properties. A new window will show up, with a list. The item *VirtualBox NDIS 6 Bridged Networking Driver* Will be unchecked. Check it and click OK. + +Try to start your virtual machine again, it should work now. diff --git a/articulos/karma-chrome-ubuntu-timezone.textile b/articulos/karma-chrome-ubuntu-timezone.textile new file mode 100644 index 0000000..1785913 --- /dev/null +++ b/articulos/karma-chrome-ubuntu-timezone.textile @@ -0,0 +1,96 @@ +title: WSL Ubuntu has no timezone set, making Chrome fail on Intl related methods, when running tests with Karma. +classes: language-markup +pubDate:2018-04-18T21:33:02+02:00 + +h1. WSL Ubuntu has no timezone set, making Chrome fail on Intl related methods, when running tests with Karma. + +p(intro). While testing an Angular CLI app, from my Windows Subsystem Linux, I got a weird error. But first of all I need to setup Google Chrome to run it in headless mode. + +To install follow the instructions layed out here: https://askubuntu.com/a/79284/469134 + +bc. sudo apt-get install libxss1 libappindicator1 libindicator7 +wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb +sudo dpkg -i google-chrome*.deb + +if dpkg fails run the following: + +bc. sudo apt-get install -f + +After that run @google-chrome --version@ to confirm it´s available. + +h2. Karma error + +With karma running, you could spend months without problems, but if your code deals with timezones you might get errors like these: + +bc. Chrome (headless) ERROR + { + "message": "Uncaught RangeError: Unsupported time zone specified undefined + at http://localhost:9876/_karma_webpack_/main.bundle.js:606:57 + RangeError: Unsupported time zone specified undefined + at Object.DateTimeFormat (native) + at Object../src/app/core/time/time-zone.ts (http://localhost:9876/_karma_webpack_/main.bundle.js:606:57) + at __webpack_require__ (http://localhost:9876/_karma_webpack_/inline.bundle.js:55:30) + at Object../src/app/core/http/index.ts (http://localhost:9876/_karma_webpack_/main.bundle.js:302:10) + at __webpack_require__ (http://localhost:9876/_karma_webpack_/inline.bundle.js:55:30) + at Object../src/app/core/index.ts (http://localhost:9876/_karma_webpack_/main.bundle.js:673:10) + at __webpack_require__ (http://localhost:9876/_karma_webpack_/inline.bundle.js:55:30) + at Object../src/app/globals/globals.module.ts (http://localhost:9876/_karma_webpack_/main.bundle.js:1650:15) + at __webpack_require__ (http://localhost:9876/_karma_webpack_/inline.bundle.js:55:30) + at Object../src/app/globals/index.ts (http://localhost:9876/_karma_webpack_/main.bundle.js:1697:24)", + "str": "Uncaught RangeError: Unsupported time zone specified undefined + at http://localhost:9876/_karma_webpack_/main.bundle.js:606:57 + RangeError: Unsupported time zone specified undefined + at Object.DateTimeFormat (native) + at Object../src/app/core/time/time-zone.ts (http://localhost:9876/_karma_webpack_/main.bundle.js:606:57) + at __webpack_require__ (http://localhost:9876/_karma_webpack_/inline.bundle.js:55:30) + at Object../src/app/core/http/index.ts (http://localhost:9876/_karma_webpack_/main.bundle.js:302:10) + at __webpack_require__ (http://localhost:9876/_karma_webpack_/inline.bundle.js:55:30) + at Object../src/app/core/index.ts (http://localhost:9876/_karma_webpack_/main.bundle.js:673:10) + at __webpack_require__ (http://localhost:9876/_karma_webpack_/inline.bundle.js:55:30) + at Object../src/app/globals/globals.module.ts (http://localhost:9876/_karma_webpack_/main.bundle.js:1650:15) + at __webpack_require__ (http://localhost:9876/_karma_webpack_/inline.bundle.js:55:30) + at Object../src/app/globals/index.ts (http://localhost:9876/_karma_webpack_/main.bundle.js:1697:24)" + } + +The error was triggered by a call to: @Intl.datetimeformat().resolvedoptions().timezone@ which at some point is undefined, because the Browser does not seem to have one. In any other environment the same config works fine. So it had to be Ubuntu. + +Let´s check the date... there are several way to do that, and you can start with @date@ + +bc. Wed Mar 28 14:21:24 DST 2018 + +but I have no idea what DST stands for, so I tried to get a more explicit one or the offset, here I bumped with a number of options (https://askubuntu.com/a/27599/469134) + +bc. cat /etc/timezone +grep UTC /etc/default/rcS +date +# hardware clock +sudo hwclock --show + +only @date@ worked for me... +and hwclock threw up the following: + +bc. hwclock: Cannot access the Hardware Clock via any known method. +hwclock: Use the --debug option to see the details of our search for an access method. + +!https://i.imgflip.com/2a6biu.jpg! + +Also found a lot of people using @timedatectl@ but guess what... + +bc. timedatectl +Failed to create bus connection: No such file or directory + +So it seems that WSL Ubuntu comes without @systemd-services@ package and if I try to install it with @apt-get@ I get: @Note, selecting 'systemd' instead of 'systemd-services'@. + +Finally found the solution at: https://github.com/HowardHinnant/date/issues/102 + +it is suggested to do the following: + +bc. rm /etc/localtime +ln -s /usr/share/zoneinfo/Europe/Berlin /etc/localtime + +but I ended up doing + +bc. sudo mv /etc/localtime /etc/no-localtime +ln -s /usr/share/zoneinfo/Europe/Berlin /etc/localtime + +And that worked perfectly to set my timezone to CEST (my actual timezone). diff --git a/config.rb b/config.rb deleted file mode 100644 index 75dd9fe..0000000 --- a/config.rb +++ /dev/null @@ -1,27 +0,0 @@ -# Require any additional compass plugins here. - -# Set this to the root of your project when deployed: -http_path = "/" -css_dir = "./css" -sass_dir = "./sass" -images_dir = "./img" -javascripts_dir = "./js" - -output_style = :expanded -# output_style = :compressed - -# You can select your preferred output style here (can be overridden via the command line): -# output_style = :expanded or :nested or :compact or :compressed - -# To enable relative paths to assets via compass helper functions. Uncomment: -# relative_assets = true - -# To disable debugging comments that display the original location of your selectors. Uncomment: -# line_comments = false - - -# If you prefer the indented syntax, you might want to regenerate this -# project again passing --syntax sass, or you can uncomment this: -# preferred_syntax = :sass -# and then run: -# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass diff --git a/css/styles.css b/css/styles.css index 5120e6a..331ebbd 100644 --- a/css/styles.css +++ b/css/styles.css @@ -1,5 +1,5 @@ @charset "UTF-8"; -@import url("http://fonts.googleapis.com/css?family=PT+Sans:400,400italic,700,700italic"); +/*@import url("https://fonts.googleapis.com/css?family=PT+Sans:400,400italic,700,700italic");*/ /* ============================================================================= HTML5 Boilerplate CSS: h5bp.com/css ========================================================================== */ @@ -551,6 +551,13 @@ figure pre { overflow-y: hidden; white-space: pre; } +/* added by hand */ +h2.subtitle, h3.subtitle { + color:#45BCD2; + font-size:20px; + margin:0; + border-bottom:1px solid #B3B3B3; +} /* line 96, ../sass/styles.scss */ article { diff --git a/home.php b/home.php index 360cf92..7b83864 100644 --- a/home.php +++ b/home.php @@ -1,18 +1,6 @@ - - - - - - +
Code Médula – Blog de código @@ -23,19 +11,10 @@ "> - + + - -