Importing dynamic path in Less mixin - import

I'm rewriting my Less css structure to be more scalable. I'm looking for an architecture that loads a templates for each media query for each template.
Preferably, I want to load this in a mixin. The current mixin looks like this (but does not allow specific component loading)
`
/**
* Progressive enhancing overrides (mobile first)
*
* Mobile loads "mobile.less"
* Wide mobile loads "mobile.less" and "widemobile.less"
* Tablet loads "mobile.less", "widemobile.less" and "tablet.less"
* etc.
*/
.progressive-enhancement() {
// Mobile layout
#media only screen {
#import (less) "../template/mobile";
}
(...)
}
So what I'm looking for is something like this (not working):
.progressive-enhancement(#component: main) {
// Mobile layout
#media only screen {
#import (less) "../template/#{component}/mobile";
}
(...)
}
This however, does not work, resulting in an error claiming that #component is undefined.
I think the problem is that Less tries to do the import before the mixing is called, not having the #component defined at that stage.
Is there any way to use #import dynamically with variables provided by the mixin?
Thanks in advance.

Yes, it's impossible. And, yes, this is because Less have to evaluate language entities in certain "typed" order instead of "top-to-bottom" order (roughly it's imports -> mixins -> variables etc.) because of lazy-evaluation principles (there're some internal workarounds possible to handle certain specific things with an exception to this, but those exceptions will never be anything but kludge).
As for your specific use-case, the easiest workaround at first glance would be to use imports instead of mixins, and let the components to specify their own names:
// progressive-enhancement.less:
#media only screen {
#import "#{component}/mobile";
}
// etc.
Then for each component you provide its "root" file:
// ../template/button.less:
& {
#component: button;
#import (multiple) "progressive-enhancement.less";
}
.
// ../template/toolbar.less:
& {
#component: toolbar;
#import (multiple) "progressive-enhancement.less";
}
etc.
And finally in your master file you just import those ordinarily:
// main.less:
#import "../template/button";
#import "../template/toolbar";
(Obviously file names and and their actual locations to be adjusted to your taste).

I'm answering my own question so i can use some formatting to show my workaround.
I have this directory structure:
less/
- components/
- navbar/
- mobile.less
- tablet.less
(...)
- config/
- defaults.less
- lib/
- grid.less
- mediaqueries.less
(...)
- template/
- base.less
- mobile.less
- widemobile.less
- tablet.less
(...)
- main.less
The main.less file import the required libraries (e.g. mediaqueries.less). These provide mixing to use (e.g. .progressive-enhancement()). The mediaqueries library has multiple mixins that take care of template loading. See the docblock:
/**
* Progressive enhancing overrides (mobile first)
*
* Mobile loads "mobile.less"
* Wide mobile loads "mobile.less" and "widemobile.less"
* Tablet loads "mobile.less", "widemobile.less" and "tablet.less"
* etc.
*/
In addition, main.less also includes template/base.less for common styling ,font loading, custom mixins etc.
Since it was not possible for the mediaqueries library to handle the components in a nice way. This logic was moved to the them files. E.g. mobile.less:
(...)
/**
* Imports
*/
#import (less) "../components/navbar/mobile.less";
#import (less) "../components/postslist/mobile.less";
#import (less) "../components/footer/mobile.less";
(...)
Whenever i need to overwrite a rule for a certain media query additional imports can be made to to other files (unfortunately no auto loading). E.g. tablet.less
(...)
/**
* Imports
*/
#import (less) "../components/navbar/tablet.less";
#import (less) "../components/postslist/tablet.less";
Note that the footer is unchanged from mobile.
This solution might be a bit more verbose than the solution provided by #seven-phases-max but I think it's cleaner since variables don't need to be abused as parameters.

Related

Babel removes jsdoc header comments. How to force it to keep them?

I have a .ts file with following code:
/**
* #ab 3.0
* #xy
*/
import * as myInterface from "#root/common/interface/interfaces";
...
I want to have the comment header at the very top of the .js file, however it either disappears in some cases or is being moved to the middle of the code in other cases. Does anyone have any idea how to configure babel to transpile it in a correct way? I am using babelrc.

Swift Package Manager Public Headers with Complicated Layouts

I have a sample Swift Package Manager package (let's call it TestPackage), that is structured in the following way:
TestPackage/
Sources/
TestPackage/
Services/
Services.h
Services.m
TestPackageUI/
UIComponent1.h
UIComponent1.m
UIComponent2.h
UIComponent2.m
include/
TestPackage.h (umbrella header)
The contents of my TestPackage.h look something like this:
/// Umbrella header
/// Services
#import "Services.h" // (or "Services/Services.h")
/// TestPackageUI
#import "Component1.h" // (or "TestPackageUI/Component1.h")
#import "Component2.h" // (or "TestPackageUI/Component2.h")
What I want is that users of this package can do import this package into objc/swift and use the Services and TestPackageUI. They could do something such as:
Objective-C:
#import TestPackage;
/// or
#import <TestPackage.h>
Swift:
import TestPackage
The SPM Usage documentation says:
In case of complicated include layouts or headers that are not compatible with modules, a custom module.modulemap can be provided in the include directory.
So I added a module.modulemap in the include directory with the following content:
module TestPackage {
header "TestPackage.h"
export *
}
But when I try to use this package, the umbrella header TestPackage.h cannot find the header files it includes. Note that these sub-directories are added as headerSearchPaths in the C Settings of the target. I would like to maintain the same project structure. Can anyone help with the correct way to write a modulemap that works with this layout? Thanks in advance.

Swift #import of module '<module name>' in implementation of <Project name>; use #import

I'm trying to create a mixed ObjC-Swift framework. But I'm losing a lot of hairs trying to make a private module for my Swift files.
I followed some steps in iOS mixed dynamic framework - bridge objc headers with private module combined with some steps in https://stackoverflow.com/a/36878037/749438
Basically I have a module.modulemap now which has the following content:
module MyCore { //Adding 'framework' before module is giving me an "Umbrella not found"-error :/
umbrella header "MyCore.h"
export *
module * { export * }
explicit module MyCorePrivate {
header "MyCore_PrivateUmbrella.h"
export *
}
}
The MyCore_PrivateUmbrella.h imports all headers I want to privately expose to my Swift code. The reason behind it is just that it's easier to include 1 header in the module then all the to-be-exposed headers (since you need to include the specific paths to the headers...).
My build settings look like:
DEFINES_MODULE: YES
PRODUCT_MODULE_NAME: MyCore
CLANG_ENABLE_MODULES: YES
SWIFT_OBJC_INTERFACE_HEADER_NAME: MyCore-Swift.h
SWIFT_INCLUDE_PATHS: path to the directory of the module.modulemap
and last but not least; ALWAYS_SEARCH_USER_PATHS is set to NO
In my Swift files I import the module using import MyCore.MyCorePrivate. This works as expected and I can use my code from Objective-C.
Building the project gives me an error like this (the black bars only hide the project name and path to the file):
Now clicking the error brings me to the generated MyCore-Swift.h where the #import MyCore.MyCorePrivate is seemingly wrong.
I've got no idea as of why it's wrong, neither do I know how to fix this. Especially since it's a file generated by XCode.
Does anyone knows what's going down here?
You will need to modify the resulting framework after building it:
1) Don't create any private modules. Revert back to default settings.
2) Any code you want to expose to swift add to your framework header and make sure the headers are set as public in the build section or else swift code wont have access. (Use the <> syntax)
3) Any code from swift to objc make public.
4) Compile you project
5) go to your framework build directory (i.e MyFramework.framework)
6) open the framework header file in the headers directory of the framework (Myframework.h file)
7) Delete all the import statements that should have been private from the framework header
8) Delete all the .h files for the headers that should have been private from the headers directory ( you removed the import statements from the main framework header)
9) go to the .module file and remove the swift modules section
The module file should be very bare bones:
framework module MyFramework {
umbrella header "MyFramework.h" export * module * {export *}}

How can I serve mostly static pages from a scala Play! application like an "About" page in different languages?

I am building an application using the Play! framework version 2.0.4. Some pages that are legally required such as an imprint mostly contain lots (some 10k each) of static text which I would like to provide in different languages.
In versions 1.x there was an #include directive that allowed to construct the actual resource path using the current Lang.
What is the recommended way of implementing sth similar with Play 2.x?
Thank you & best regards,
Erich
I'm not 100% certain how you implement it as of now, but here's what I've come up with.
You could just write your own include helper. Save the following in a file Helpers.scala in your views folder. Explanations are in the code's comments.
package views.html.helper
object include {
import play.api.templates.Html
import play.api.Play
import play.api.Play.current
import play.api.i18n._
// The default is to look in the public dir, but you can change it if necessary
def apply(filePath: String, rootDir: String = "public")(implicit lang: Lang): Html = {
// Split filePath at name and suffix to insert the language in between them
val (fileName, suffix) = filePath.splitAt(filePath.lastIndexOf("."))
// Retrieve the file with the current language, or as a fallback, without any suffix
val maybeFile =
Play.getExistingFile(rootDir + "/" + fileName + "_" + lang.language + suffix).
orElse(Play.getExistingFile(rootDir + "/" + filePath))
// Read the file's content and wrap it in HTML or return an error message
maybeFile map { file =>
val content = scala.io.Source.fromFile(file).mkString
Html(content)
} getOrElse Html("File Not Found")
}
}
Now in your imprint.scala.html you could call it like this:
#()(implicit lang: Lang)
#import helper._
#include("static/imprint.html")
Way showed by Schleichardt was used in play-authenticate to select mail templates in different languages and now it's changed to work with reflections on the controller, so maybe it can be interesting for you. Anyway it was intendent to keep standard templating possibilities (cause each mail need to be personalized before send)
For static info pages, you can just save the code for each language with suffix ie. impressum_en.html, impressum_de.html in the file system and use simple controller which will find file with proper suffix and return its content exactly as it is... all you need probably to return Ok(fileContent) and set the Content-Type manually to text/html.
Other option is doing the similar thing but storing it in the DB, so you can create simple back-end and edit it with browser.
If you still need to replace some elements, you can do it with some ###MARKER### in the code + simple String operations, or with JavaScript on the client side.
Templates in 2.0 work a bit differently. The Scala based templates are compiled. From one template instead of 'including' another, you can make a call to it. I'm not sure exactly what you mean by the language thing. In 2.0 though, a parameter to the template could be the language.
Example template named 'included' in package whateverpackage.
#(lang: Lang)
...
Example calling a template named 'included':
#import whateverpackage._
#included(Lang("en"))
#()(implicit lang: Lang)
#main(Messages("imprint")) {
#lang match {
case Lang("de", _) => { #germanImprint() #* uses app/views/germanImprint.scala.html file *#}
case _ => { #englishImprint() }
}
}

Zend Framework Controller to Module routing

So i have been doing my best trying to absorb as much as i can about the Zend Framework which is pretty new to me, i'm about two weeks in since my first attempts and being doing well so far.
However i have run into a small issue i just can't figure out.
So here's the deal, i have a standard Zend Framework project with a number of modules in it. Like this :
- Project
- - Application
- - - configs
- - - controllers
- - - - IndexController
- - - - WMSController
- - - forms
- - - layouts
- - - models
- - - modules
- - - - content
- - - - - controllers
- - - - - - IndexController
- - - - - models
- - - - - views
- - - - - Bootstrap
- - - views
- - - bootstrap
- - public
etc..
Now i have a simple test link set in the view for the WMSController wich is supposed to direct someone klicking it to the IndexController of the content module.
test link to content module
Now as you can probably see this link is NOT going to work since it is pointing towards localhost/wms/content which would be the content action in the WMSController which doesn't exist at this moment.
Now what i want to do is to make the wms/content actually point towards the IndexController of the content module. Why? Well i simply do not want a user to type localhost/content to get to the content module which is part of the WMS. I want to force them to get trough the WMS controller first.
I have read numerous things about routing being the solution using the bootstrap or the autoloader but pretty much all of them simply help you with pointing a certain url to a specific action in a specific controller.
What i want is a url to point to a specific action in a specific controller in a specific module.
NOTE: All the other controllers and views are still the default generated versions with no changes made to them yet!
If anyone could show me a code example of how this is done it would be much appreciated!
If I understand correctly you simply want /wms/content to point to module content controller Index action index. This is a case where a simple router will work(at least until you want to get more complex)
In your application.ini add these lines:
resources.router.routes.content.route = "wms/content"
resources.router.routes.content.defaults.module = "content"
resources.router.routes.content.defaults.controller = "index"
resources.router.routes.content.defaults.action = "index"
this is the easiest way to build a custom route.
*Note:*The 4th parameter from the left is the name of the route, so if you use it with a method that allows using route names (the url() helper for example) you can just use the route name. $this->url(array(), 'content');
This is how you would use a named route, personally I would probably consider renaming my module wms (if possible and practical) and just redirecting there from the default Index controller. Because once you start with named and custom routes it's hard to quit...
From your question that you
want to force them to get trough the WMS controller first
You can do one thing. Whatever you want to do in WMSController whenever a user types localhost/content/** you can put it in the parent class for ALL THE CONTROLLERS IN MODULE: 'CONTENT'. This way you can check for something/ perform operations everytime a request comes to this controller (no matter if the user wanted to go to the other module.)
class Content_AnyController extends MyControllers_Controller_Action_Admin{
....
}
where
class Reviewmo_Controller_Action extends Zend_Controller_Action{
public function init(){
//Things you want to do each time
}
}
This is what I think you want to achieve because if you want to just simply redirect to WMSController's ContentAction you can simply redirect to that controller.