React and LESS, use a dynamic value from process.env for variables - reactjs

I have an app with React with LESS.
I have a "mixins" LESS file like this:
#STATICS: "https://should-be-set-on-env";
#STATICS_KEY: "key-should-be-set-on-env";
.completePath(#property, #path) when (#property = 'background-image'){
background-image: url("#{STATICS}/#{path}#{STATICS_KEY}") !important;
}
Currently I'm overwriting the #STATIC and #STATIC_KEY with some method that has customize-cra but now I can't use them (for X reason).
I need a way to read directly from the process.env values in order to have something like this:
#STATICS: readFromProcesEn(REACT_APP_STATICS);
#STATICS_KEY: readFromProcesEn(REACT_APP_STATICS_KEY);
How can I co it? is there a way with Less to read from an external file or some sort of JavaScript function, to get those values from process.env ?

This works for me:
#STATICS: `(function(){return process.env.REACT_APP_STATICS;})()`;
#STATICS_KEY: `(function(){return process.env.REACT_APP_STATICS_KEY;})()`;
Didn't know that Less could use javascript inside batticks.

Related

How to read a text file from resources without javaClass

I need to read a text file with readLines() and I've already found this question, but the code in the answers always uses some variation of javaClass; it seems to work only inside a class, while I'm using just a simple Kotlin file with no declared classes. Writing it like this is correct syntax-wise but it looks really ugly and it always returns null, so it must be wrong:
val lines = object {}.javaClass.getResource("file.txt")?.toURI()?.toPath()?.readLines()
Of course I could just specify the raw path like this, but I wonder if there's a better way:
val lines = File("src/main/resources/file.txt").readLines()
Thanks to this answer for providing the correct way to read the file. Currently, reading files from resources without using javaClass or similar constructs doesn't seem to be possible.
// use this if you're inside a class
val lines = this::class.java.getResourceAsStream("file.txt")?.bufferedReader()?.readLines()
// use this otherwise
val lines = object {}.javaClass.getResourceAsStream("file.txt")?.bufferedReader()?.readLines()
According to other similar questions I've found, the second way might also work within a lambda but I haven't tested it. Notice the need for the ?. operator and the lines?.let {} syntax needed from this point onward, because getResourceAsStream() returns null if no resource is found with the given name.
Kotlin doesn't have its own means of getting a resource, so you have to use Java's method Class.getResource. You should not assume that the resource is a file (i.e. don't use toPath) as it could well be an entry in a jar, and not a file on the file system. To read a resource, it is easier to get the resource as an InputStream and then read lines from it:
val lines = this::class.java.getResourceAsStream("file.txt").bufferedReader().readLines()
I'm not sure if my response attempts to answer your exact question, but perhaps you could do something like this:
I'm guessing in the final use case, the file names would be dynamic - Not statically declared. In which case, if you have access to or know the path to the folder, you could do something like this:
// Create an extension function on the String class to retrieve a list of
// files available within a folder. Though I have not added a check here
// to validate this, a condition can be added to assert if the extension
// called is executed on a folder or not
fun String.getFilesInFolder(): Array<out File>? = with(File(this)) { return listFiles() }
// Call the extension function on the String folder path wherever required
fun retrieveFiles(): Array<out File>? = [PATH TO FOLDER].getFilesInFolder()
Once you have a reference to the List<out File> object, you could do something like this:
// Create an extension function to read
fun File.retrieveContent() = readLines()
// You can can further expand this use case to conditionally return
// readLines() or entire file data using a buffered reader or convert file
// content to a Data class through GSON/whatever.
// You can use Generic Constraints
// Refer this article for possibilities
// https://kotlinlang.org/docs/generics.html#generic-constraints
// Then simply call this extension function after retrieving files in the folder.
listOfFiles?.forEach { singleFile -> println(singleFile.retrieveContent()) }
In order to have the same url that work for both Jar or in local, the url (or path) needs to be a relative path from the repository root.
..meaning, the location of your file or folder from your src folder.
could be "/main/resources/your-folder/" or "/client/notes/somefile.md"
The url must be a relative path from the repository root.
it must be "src/main/resources/your-folder/" or "src/client/notes/somefile.md"
Now you get the drill, and luckily for Intellij Idea users, you can get the correct path with a right-click on the folder or file -> copy Path/Reference.. -> Path From Repository Root (this is it)
Last, paste it and do your thing.

How to set a context variable with dot in name?

I am trying to add a context data variable (CDV), which has a dot in its name. According to Adobe site this is correct:
s.contextData['myco.rsid'] = 'value'
Unfortunately, after calling s.t() the variable is split into two or more:
Context Variables
myco.:
rsid: value
.myco:
How can I set the variable and prevent splitting it into pieces?
You are setting it properly already. If you are referring to what you see in the request URL, that's how the Adobe library sends it. In your example, "myco" is a namespace, and "rsid" is a variable in that namespace. And you can have other variables in that namespace. For example if you have
s.contextData['myco.rsid1'] = 'value';
s.contextData['myco.rsid2'] = 'value';
You would see in the AA request URL (just showing the relevant part):
c.&myco.&rsid1=value&rsid2=value&.myco&.c
I assume you are asking because you want to more easily parse/qa AA collection request URLs from the browser network tab, extension, or some unit tester? There is no way to force AA to not behave like this when using dot syntax (namespaces) in your variables.
But, there isn't anything particularly special about using namespaces for your contextData variables; it's just there for your own organization if you choose. So if you want all variables to be "top level" and show full names in the request URL, then do not use dot syntax.
If you want to still have some measure of organization/hierarchy, I suggest you instead use an underscore _ :
s.contextData['myco_rsid1'] = 'value';
s.contextData['myco_rsid2'] = 'value';
Which will give you:
c.&myco_rsid1=value&myco_rsid2=value&.c
Side Note: You cannot do full object/dot notation syntax with s.contextData, e.g.
s.contextData = {
foo:'bar', // <--- this will properly parse
myco:{ // this will not properly parse
rsid:'value' //
} //
};
AA library does not parse this correctly; it just loops through top level properties of contextData when building the request URL. So if you do full object syntax like above, you will end up with:
c.&foo=bar&myco=%5Bobject%20Object%5D&&.c
foo would be okay, but you end up with just myco with "[object Object]" as the recorded value. Why Adobe didn't allow for full object syntax and just JSON.stringify(s.contextData) ? ¯\_(ツ)_/¯

The code of `for-of` circlation transport by babel not support some browser

I had some es6 codes in my react project like this:
``` javascript
for (const v of [0, 1, 2,]) { /* doSth*/ }
```
and it works well after transport to es5 every where.
however, if I change them like those:
``` javascript
const arr = [0, 1, 2,];
for (const v of arr) { /* doSth*/ }
```
then it throw an error that ReferenceError: Can't find variable: Symbol in iPhone 5c.
I tried both foreach for-in and the pure for circulation, they all works well in that old device.
But, I need do something like async () => { for (...) { await doSthAysnc; } }, and it cannot use foreach.
What's more, for-of was very dangerous, and pure for is very ugly. so if possibly, I prefer to use for-of.
thanks.
#Bergi Well, that's the codes it transpiles to:
javascript
("================================================================"),m=["a","b","c"],e.prev=38,v=c.a.mark(function e(n){return c.a.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,new Promise(function(e){return setTimeout(function(){return e(n)},1e3)});case 2:case"end":return e.stop()}},e,t)}),y=!0,b=!1,w=void 0,e.prev=43,_=m[Symbol.iterator]();case 45:if(y=(x=_.next()).done){e.next=51;break}return E=x.value,e.delegateYield(v(E),"t2",48);case 48:y=!0,e.next=45;break;case 51:e.next=57;break;case 53:e.prev=53,e.t3=e.catch(43),b=!0,w=e.t3;case 57:e.prev=57,e.prev=58,!y&&_.return&&_.return();case 60:if(e.prev=60,!b){e.next=63;break}throw w;case 63:return e.finish(60);case 64:return e.finish(57);case 65:e.next=69;break;case 67:e.prev=67,e.t4=e.catch(38);case 69:console.log("================================================================"),
Using an array literal directly inside for … of enables an extra transpiler optimisation that causes it not to use iterables. In the default cause, it will try to find the m[Symbol.iterable] method which fails in legacy environments.
In can see three solutions:
Import the babel-polyfill to enable symbols and iterators
Use loose mode which hopefully always uses the array path
Use the transform-for-of-as-array babel plugin instead which always transpiles to array loops

Build an array from yaml in rails

I'm working on a simple rails app that does SMS. I am leveraging Twilio for this via the twilio_ruby gem. I have 10 different phone numbers that I want to be able to send SMS from randomly.
I know if I do something like this:
numbers = ["281-555-1212", "821-442-2222", "810-440-2293"]
numbers.sample
281-555-1212
It will randomly pull one of the values from the array, which is exactly what I want. The problem is I don't want to hardcode all 10 of these numbers into the app or commit them to version control.
So I'm listing them in yaml (secrets.yml) along with my Twilio SID/Token. How can I build an array out of the 10 yaml fields i.e. twilio_num_1, twilio_num_2, etc, etc so that I can call numbers.sample?
Or is there a better way to do this?
You can also use
twilio_numbers:
- 281-555-1122
- 817-444-2222
- 802-333-2222
thus you don't have to write the numbers in one line.
Figured this out through trial and error.
In secrets.yml
twilio_numbers: ["281-555-1122","817-444-2222","802-333-2222"]
In my code:
Rails.application.secrets.twilio_numbers.sample
Works like a charm.
create a file: config/twilio_numbers.yml
---
- 281-555-1122
- 817-444-2222
- 802-333-2222
and load it in your config/application.rb like this:
config.twilio_numbers = YAML.load_file 'config/twilio_numbers.yml'
you can then access the array from inside any file like this:
Rails.application.config.twilio_numbers
=> ["281-555-1122", "817-444-2222", "802-333-2222"]

Custom output with capistrano 3

I need to change output which is generated with sshkit formatters, and I can't install additional gems, but I can adjust my capistrano 3 configs. At first I tried just create new Formatter (I just copy paste pretty formatter, and made some output changes). like this https://gist.github.com/Dariusp/3e455fdb78b9f8636289
than set :format, :improvedformatter in deploy.rb file. And add
require_relative 'lib/improved_formatter'
to Capfile.
But I always get error "Abstract formatter should not be used directly, maybe you want SSHKit::Formatter::BlackHole", like I am trying use abstract formatter directly. if I try extend PrettyFormater, I get PrettyFormatter output, without my changes. It seems like always it execute parent class method. Its there any way how to create and set custom formatter in my capistrano configs ?
I ran into the exact same issue when I wanted to override the pretty formatter.
The problem was that I needed to also define the "<<" operator as this is defined as an alias in the base class and aliases are not inherited.
in deploy.rb:
set :format, :myformatter
in Capfile:
require 'lib/sshkit/formatters/myformatter'
in lib/sshkit/formatters/myformatter.rb:
module SSHKit
module Formatter
class MyFormatter < Pretty
def <<(obj)
write(obj)
end
def write(obj)
...
end
end
end
end

Resources