Nuxt.js - force trailing slash at the end of all urls - vue.js

I'm looking for a way to make sure that all of my urls end with a trailing slash (so first check if there is already a trailing slash at the end, and if not add one).
I have tried with nuxt-redirect-module, and it works adding the slash but then it leads to an infinite redirect
redirect: [
{
from: '^(.*)$',
to: (from, req) => {
let trailingUrl = req.url.endsWith('/') ? req.url : req.url + '/'
return trailingUrl
}
}
]
Any insight will be welcome. Thanks!

The following regex handles query string as well:
redirect: [
{
from: '^(\\/[^\\?]*[^\\/])(\\?.*)?$',
to: '$1/$2',
},
],

You can try to match only those URLs that do not end with a slash:
redirect: [
{
from: '^.*(?<!\/)$',
to: (from, req) => req.url + '/'
}
]

I had the same problem, but I didn't want to use the redirects. I tried a lot of solutions, but finally it turned out that adding a double slash to the routing path had the desired effect:
router: {
prefetchLinks: false,
middleware: 'navigation',
routeNameSplitter: '/',
extendRoutes(routes, resolve) {
routes.push(
{
name: 'kaufen',
path: '/kaufen//',
component: resolve(__dirname, 'pages/listing/index.vue'),
},
{
name: 'mieten',
path: '/mieten//',
component: resolve(__dirname, 'pages/listing/index.vue'),
},
This results in:
https://example.com/kaufen/?alternate=true&ignoreToplisting=false
It seems very hacky, but it does the trick!

Related

Vite proxy server rewrite

/**
* Generate proxy
* #param list
*/
export function createProxy(list: ProxyList = []) {
const ret: ProxyTargetList = {};
for (const [prefix, target] of list) {
const isHttps = httpsRE.test(target);
// https://github.com/http-party/node-http-proxy#options
ret[prefix] = {
target: target,
changeOrigin: true,
ws: true,
rewrite: (path) => path.replace(new RegExp(`^${prefix}`), ''),
// https is require secure=false
...(isHttps ? { secure: false } : {}),
};
}
console.log('proxy list');
console.log(ret);
return ret;
}
I have above method to create a list of proxy based on different prefix which defined in .env.development.
VITE_PROXY = [["/basic-api","http://127.0.0.1:3100"],["/api","http://127.0.0.1:8080"],["/upload","http://localhost:3300/upload"]]
But when I request url http://127.0.0.1/api/xxx, it is not rewrite to http://127.0.0.1:8080 as expected.
then I just add return path in rewrite function like this:
rewrite: (path) =>
{path.replace(new RegExp(`^${prefix}`), '');return path},
Then it works.
I am confused now. What's the difference there? I googled a lot about vite proxy rewrite, normally, no need to add return statement like I just did.
Thanks!
Hint: rewrite: (path) => {path.replace(new RegExp(^${prefix}), '');return path},
will return you the original, untransformed path, since replace returns a new string. Please see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace.
So probably the regex or underlying logic is not correct.

Commitlint - Allow '/' in scope-enum

In my Angular project, I want to extend #commitlint/config-conventional with some pre-defined scopes.
The Angular project has a library for UI components (generated via ng generate library) and a default app which consumes the UI library.
In commitlint.config.js I've added the following lines:
module.exports = {
extends: ['#commitlint/config-conventional'],
rules: {
'scope-enum': [
2,
'always',
[
'ui-components',
'ui-components/badge',
'ui-components/button',
'ui-components/tooltip',
'core',
'account',
'plugins',
'settings',
'projects',
'shared',
'styles'
]
]
}
};
However, when I try to commit something with the scope: 'ui-components/tooltip':
fix(ui-components/tooltip): fix border
I get a commitlint error, saying that:
⧗ input: fix(ui-components/tooltip): fix border
✖ scope must be one of [ui-components, ui-components/badge, ui/button, ui-components/tooltip, core, account, plugins, settings, projects, shared, styles] [scope-enum]
✖ found 1 problems, 0 warnings
Unfortunately slashes aren't allowed in scopes.
To get around this I replace / with two dashes (--).
I wrote a script to grab subfolders and return an array:
https://gist.github.com/trevor-coleman/51f1730044e14081faaff098618aba36
[
'ui-components',
'ui-components--badge',
'ui-components--button',
'ui-components--tooltip',
...
]
According to source code, Commitlint use / for multiple scopes.
It means, you can commit like fix(core/account): fix border but you can't commit fix(ui-components/tooltip): fix border because you need to add tooltip in to your scopes first.
Here is source code: https://github.com/conventional-changelog/commitlint/blob/master/%40commitlint/rules/src/scope-enum.ts
Also, it is mentioned in here: https://github.com/conventional-changelog/commitlint/blob/master/docs/concepts-commit-conventions.md#multiple-scopes
You can write your own custom plugin to check scopes, I had the same issue, so I wrote one to solve this problem, see example commitlint.config.js below:
module.exports = {
extends: ["#commitlint/config-conventional"],
rules: {
"enhanced-scope-enum": [
2,
"always",
[
"ui-components",
"ui-components/badge",
"ui-components/button",
"ui-components/tooltip",
"core",
"account",
"plugins",
"settings",
"projects",
"shared",
"styles",
],
],
},
plugins: [
{
rules: {
"enhanced-scope-enum": (parsed, when = "always", value = []) => {
if (!parsed.scope) {
return [true, ""];
}
// only use comma sign as seperator
const scopeSegments = parsed.scope.split(",");
const check = (value, enums) => {
if (value === undefined) {
return false;
}
if (!Array.isArray(enums)) {
return false;
}
return enums.indexOf(value) > -1;
};
const negated = when === "never";
const result =
value.length === 0 ||
scopeSegments.every((scope) => check(scope, value));
return [
negated ? !result : result,
`scope must ${negated ? `not` : null} be one of [${value.join(
", "
)}]`,
];
},
},
},
],
}

Vue Router "push" how to preserve path's query string

router.js
...
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/x',
name: 'X',
component: X
}
];
...
x.vue
...
mounted() {
const definedElsewhere = '/?a=b&c=d';
this.$router.push({ path: definedElsewhere });
// This seems to work but I don't know how to access "resolve()"
// inside "beforeRouteEnter()" with "next()".
// this.$router.push(this.$router.resolve(definedElsewhere));
}
...
Good: I'm redirected "Home".
Bad: The query string is not preserved unless I use query: { a: 'b', c: 'd' }.
Question: Is there a way to preserve the query string without using query{} inside push()?
If you're dealing with a hardcoded string, you can just pass that into the push method as-is. Check out the first example in the documentation.
this.$router.push(definedElsewhere);

How to define messages with react-i18next

I'd like to ask a question about whether react-i18next provides us a way to define messages as react-intl
I wanna define all my messages first then using i18next-scanner to extract to json file.
Thanks in advance for your help in this matter.
After a while of researching. I'd give my way to someone wanna define messages in such a messages.js. BTW, I'm using i18nxt-scanner to extract the messages to JSON file.
i18next-scanner.config.js
module.exports = {
input: [
'src/app/**/*.{js,jsx}',
// Use ! to filter out files or directories
'!app/**/*.spec.{js,jsx}',
'!app/i18n/**',
'!**/node_modules/**',
],
output: './',
options: {
debug: true,
removeUnusedKeys: true,
func: {
list: ['getTranslationId'],
extensions: ['.js', '.tsx'],
},
lngs: ['en', 'ko'],
ns: ['translation'],
defaultLng: 'en',
defaultNs: 'translation',
defaultValue: '',
resource: {
loadPath: 'src/locales/{{lng}}/{{ns}}.json',
savePath: 'src/locales/{{lng}}/{{ns}}.json',
jsonIndent: 2,
lineEnding: '\n',
},
nsSeparator: false, // namespace separator
keySeparator: false, // key separator
interpolation: {
prefix: '{{',
suffix: '}}',
},
},
};
messages.js
import { getTranslationId } from 'locales/utils';
const messages = {
title: getTranslationId('Homepage_title', {
defaultValue: 'hello, {{name}}',
}),
count: getTranslationId('Homepage_count', {
defaultValue: '{{count}} time',
count: 0, // for plurals
}),
};
export default messages;
locales/utils.js
export const getTranslationId = id => {
if (!id || !id.includes('_'))
throw new Error('ID pattern should be "BLOCK_ElEMENT"');
return id;
};
Extracting command
yarn run i18next-scanner
Hope this helps! :D

emberjs transitionToRoute nested dynamic

When I call the following :
this.get('controller').transitionToRoute('dashboards.submenu', {dashboard_id: "31", item_id: "97", subitem_id: "11"} );
I've also tried:
this.get('controller').transitionToRoute('dashboards.submenu', dash, item, subitem);
without success...
My url goes like this :
localhost:9000/#/dashboards/undefined/undefined/undefined
Unfortunately I would of like it to be
localhost:9000/#/dashboards/31/97/11
Any idea why?
If I go directly to
localhost:9000/#/dashboards/31/97/11
It works properly....
this is my router....
App.Router.map(function () {
this.resource("index", { path: "/" });
this.resource("dashboards", { path: "/dashboards" } , function(){
this.route("main", { path: '/' });
this.route("index", { path: '/:dashboard_id' });
this.route("submenu", { path: '/:dashboard_id/:item_id/:subitem_id' });
});
});
You need to implement both model and serialize methods for your route. For example:
model: function(params) {
return Ember.Object.create({dashboard_id: params.dashboard_id, item_id: params.item_id, subitem_id: params.subitem_id});
},
serialize: function(model) {
return {dashboard_id: model.get('dashboard_id'), item_id: model.get('item_id'), subitem_id: model.get('subitem_id')};
},