How Vue knows which prefix should prepend when different browser? - vue.js

Like
<template>
<h1 :style={ filter: 'blur(1px)' }>My Template!!</h1>
</template>
I used style and webkit to search source code from node_modules/Vue and node_modules/#Vue, but had no luck.
How Vue knows which prefix should prepend when different browser?? So magic it is!!
https://v2.vuejs.org/v2/guide/class-and-style.html#Auto-prefixing

I suppose I found the answer.
The code is under vue/src/platforms/web/runtime/modules/style.js line 32
const vendorNames = ['Webkit', 'Moz', 'ms']
let emptyStyle
const normalize = cached(function (prop) {
emptyStyle = emptyStyle || document.createElement('div').style
prop = camelize(prop)
if (prop !== 'filter' && (prop in emptyStyle)) {
return prop
}
const capName = prop.charAt(0).toUpperCase() + prop.slice(1)
for (let i = 0; i < vendorNames.length; i++) {
const name = vendorNames[i] + capName
if (name in emptyStyle) {
return name
}
}
})
The emptyStyle here is CSSStyleDeclaration from browser.
Vue will check every attribute with prefix in CSSStyleDeclaration or not.
If yes then will append it and cache it.
However, it looks like the filter attribute is an exception here.
Most of CSS we will write in CSS file then it will be compiled by PostCSS and Autoprefixer. Consider the runtime, the code above I guess is the easiest and smallest way to achieve, yet still have some surprises.

Related

Invalid Call on require from props url

I am attempting to set imageContent into an <Image source={imageContent}/> by getting content using require(props.imageUrl). Strangely (to me at least), the code works if I set image explicitly but fails on using props.imageUrl when equating them returns true.
export const SomeComponent: React.FC<Props> = (props: Props) => {
if (props.imageUrl != null) {
const imageUrl = '../../assets/images/profile_avatar.png'; //hardcode
const imageUrlFromProps = props.imageUrl; //from Props
console.log(imageUrl === imageUrlFromProps); //true
//SectionImage = require(imageUrl); //Works
//SectionImage = require(imageUrlFromProps); //Err: Invalid Call
}
...
<Image source={SectionImage}/>
Ciao, for what I know, require doesn't work with dynamic value. According to this discussion, the reason of this problem is how require is loaded. Seems that require is loaded before runtime and if it doesn't find a resource at this time, it doesn't work .
If you really need to assign dynamic resource to require, what I always do is create an array of require like:
var resources = {
res1: require("res1.png"),
res2: require("res2.png"),
...
}
and then when I need to load one of these at runtime:
if (condition) {
SectionImage = resources.res1;
}
else SectionImage = resources.res2;
As Giovanni has suggested, require can't be dynamic. It expects static strings only (Imagine how would all static bundling would have worked if they were dynamic). The only reason I didn't vote that as the answer is because I wanted to make the component more generic. So instead of applying condition in component, I imported image from the parent component and passed into this component (which I directly set to Source).
From Parent:
import Avatar from '../../assets/images/profile_avatar.png'
...
<SomeComponent image={Avatar}/>
and in Somecomponent:
let sectionImage = props.image || null;
...
<Image source={sectionImage}/>

Adding embedded mode in docusaurus

I am using docusaurus 1.14.4
I need to create embedded mode for each document which remove header, footer and left navigation.
Page url look like this http://localhost:3000/...../?mode=emb
I figure out a way by adding this piece of script to each md file
<script>
function getParameterByName(name) {
var match = RegExp('[?&]' + name + '=([^&]*)').exec(window.location.search);
return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
}
var mode = getParameterByName('mode');
if (mode === 'emb') {
setTimeout(()=>{
let list = ['fixedHeaderContainer', 'docsNavContainer', 'nav-footer', 'docs-prevnext'];
for (var itemClassName of list) {
var item = document.getElementsByClassName(itemClassName)[0]
item.parentNode.removeChild(item)
}
document.getElementsByClassName('navPusher')[0].style.paddingTop = 0;
document.getElementsByClassName('mainContainer')[0].style.paddingTop = 0;
}, 0)
}
</script>
It work but does not look like a proper way. Can anyone suggest a better way?
Docusaurus maintainer here. There's no supported way of doing this. May I know what your motivations for doing this are?

How can I use "<nuxt-link>" in content rendered with "v-html"?

I have a utilities plugin for Nuxt.js that I created with a method to parse hashtags and mentions and replace them with <nuxt-link>. I am then using v-html to inject the converted data back into the template. My issue is that the <nuxt-link> are not being parsed with v-html.
import Vue from 'vue';
Vue.mixin({
methods: {
replaceMentions(data) {
// Tags
const tagRegEx = /\[#tag:[a-zA-Z0-9_-]*\]/g;
let tagMatch;
while ((tagMatch = tagRegEx.exec(data)) !== null) {
const tag = Array.from(tagMatch[0].matchAll(/\[#tag:(.*?)\]/g));
data = data.replace(tag[0][0], '<nuxt-link to="/search?q=' + tag[0][1] + '">#' + tag[0][1] + '</a>');
};
// Users
const userRegEx = /\[#user:[a-zA-Z0-9_-]*\]/g;
let userMatch;
while ((userMatch = userRegEx.exec(data)) !== null) {
const user = Array.from(userMatch[0].matchAll(/\[#user:(.*?)\]/g));
data = data.replace(user[0][0], '<nuxt-link to="/users/' + user[0][1] + '">#' + user[0][1] + '</>');
};
return data;
}
}
});
Does anyone have any tips for how I could make these work as proper nuxt compatible links? I already tried using <a> and it works fine, I would just prefer to utilize proper nuxt compatible links.
I think the discussion here basically answers the question: https://github.com/nuxt-community/modules/issues/185
Summarized, there are two options:
Render the HTML with a full Vue build and then attach the rendered node.
(Preferred) Find the links in the HTML and make them call router push instead of their default action.

Polymer2 Shadow dom select child element

I am working on a polymer2 shadow dom template project need to select children elements from parent elements. I found this article introduces a way to select child shadow dom elements that like this:
// No fun.
document.querySelector('x-tabs').shadowRoot
.querySelector('x-panel').shadowRoot
.querySelector('#foo');
// Fun.
document.querySelector('x-tabs::shadow x-panel::shadow #foo');
However, when I tried in my polymer2 project, like this:
//First: works!!
document.querySelector('container')
.shadowRoot.querySelector('app-grid')
.shadowRoot.querySelector('#apps');
//Second: Doesn't work!// got null
document.querySelector('container::shadow app-grid::shadow #apps')
// Thrird: document.querySelector('* /deep/ #apps') // Doesn't work, got null
I really need the second way or the third, which to put selectors in (), but both couldn't work. Does anyone know why the second one doesn't work? Thank you so much!
::shadow and /deep/ has never(?) worked in Firefox, and is depraved in Chrome 63 and later.
Source
Eric Biedelman has written a nice querySelector method for finding all custom elements on a page using shadow DOM. I wouldn't use it myself, but I have implemented it so I can "querySelect" custom elements in the console. Here is his modified code:
// EXAMPLES
// findCustomElement('app-grid') // Returns app-grid element
// findCustomElements('dom-if') // Returns an array of dom-if elements (if there are several ones)
// findCustomElement('app-grid').props // Returns properties of the app-grid element
function findCustomElement(customElementName) {
const allCustomElements = [];
customElementName = (customElementName) ? customElementName.toLowerCase() : customElementName;
function isCustomElement(el) {
const isAttr = el.getAttribute('is');
// Check for <super-button> and <button is="super-button">.
return el.localName.includes('-') || isAttr && isAttr.includes('-');
}
function findAllCustomElements(nodes) {
for (let i = 0, el; el = nodes[i]; ++i) {
if (isCustomElement(el)) {
el.props = el.__data__ || el.__data || "Doesn't have any properties";
if (customElementName && customElementName === el.tagName.toLowerCase()) {
allCustomElements.push(el);
} else if (!customElementName) {
allCustomElements.push(el);
}
}
// If the element has shadow DOM, dig deeper.
if (el.shadowRoot) {
findAllCustomElements(el.shadowRoot.querySelectorAll('*'));
}
}
}
findAllCustomElements(document.querySelectorAll('*'));
if (allCustomElements.length < 2) {
return allCustomElements[0] || customElementName + " not found";
} else if (customElementName) {
allCustomElements.props = "Several elements found of type " + customElementName;
}
return allCustomElements;
}
Remove the if (isCustomElement(el)) { statement, and you can querySelect whatever element and get an array of it if several of them exists. You can change findAllCustomElements to implement a smarter querySelect using the recursive loop on shadowDoom as base. Again, I wouldn't use this myself – and instead pass on variables from parent element(s) to children where the children have observers that activates specific behaviors – but I wanted to give you a general implementation of a fallback if nothing else works.
The problem with your question is that you don't give any specifics about WHY you want to select the children in the first place.

Specifying a specific module system when compiling Elm (vs. runtime checks)

Is there an option to let Elm know which module system you're targeting during compile time? E.g. something like a --target flag. I must admit that I haven't dug into elm-make that much.
Currently it seems that it only occurs during runtime:
elm-make/issues/50
src/Pipeline/Generate.hs
For my situation I'm:
Using Electron which defines it's own module object and a global window.
Only using Elm for a portion of the project (See HTML interop).
By default, the compiled output defaults to exposing Elm on module.exports:
if (typeof define === "function" && define['amd'])
{
define([], function() { return Elm; });
return;
}
if (typeof module === "object")
{
module['exports'] = Elm;
return;
}
var globalElm = this['Elm'];
if (typeof globalElm === "undefined")
{
this['Elm'] = Elm;
return;
}
In debug tools:
Instead, I want it to expose it on this/window and not overwrite module.exports with the Elm object.
I was able to hack together a solution that abuses the AMD check:
<script>
window.define = (arr, fn) => {
const Elm = fn();
window.Elm = Elm;
};
window.define.amd = true;
</script>
<script src="build/tronwm.js"></script>
<script>
const node = document.getElementById('elm-render');
const app = window.Elm.TronWM.embed(node);
</script>
This works for now, but curious of alternate solutions if any.
As of 0.18, no there is not. The Elm compiler does not know about details of JS Loaders etc.