Skip to content

Commit

Permalink
feat: allow custom component path separators
Browse files Browse the repository at this point in the history
  • Loading branch information
nhedger committed Mar 11, 2023
1 parent 45576ce commit cc9af45
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 9 deletions.
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,46 @@ Here a some common patterns for different project types:
| Laravel + Vue | `resources/js/Pages/**/*.vue` |
| Laravel + React | `resources/js/Pages/**/*.tsx` |

### `inertia.pathSeparators`

Inertia.js commonly uses a forward slash when it comes to component names
because it naturally follows the filesystem structure, but while the components
will eventually have to be resolved to a filesystem path, nothing prevents you
from using different path separators inside the inertia methods.

#### Component resolution

This setting allows you to define a list of path separators that the extension
should handle when resolving components paths on click, and during
autocompletion. This setting only affects how the extension, and you will have
to change the way component resolution works in your Inertia.js application in
order to replaces those characters by a forward slash `/`.

Here's an example snippet that handles components paths written with
dot-notation.

```js
import { createApp, h } from 'vue';
import { createInertiaApp } from '@inertiajs/vue3';

createInertiaApp({
resolve: (name) => {
const pages = import.meta.glob('./Pages/**/*.vue', { eager: true });
return pages[`./Pages/${name.replaceAll('.', '/')}.vue`];
},
setup({ el, App, props, plugin }) {
createApp({ render: () => h(App, props) })
.use(plugin)
.mount(el);
},
});
```

#### Autocompletion

During autocompletion, the first separator will be used when rendering the list
of components, so you should put your preferred path separator first.

### `inertia.defaultExtension`

When the extension generates hyperlinks to components that do not yet exist on
Expand Down
16 changes: 13 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@
"default": "resources/js/Pages/**/*.vue",
"description": "A glob pattern to match the Vue components that you use as pages in your Inertia application. The root folder of your components is inferred from the glob pattern."
},
"inertia.pathSeparators": {
"type": "array",
"items": {
"type": "string"
},
"default": [
"/"
],
"markdownDescription": "The allowed path separators for component names.\n\n**This setting only affects how the extension resolves the component paths and autocompletion, and you must ensure that you Inertia setup handles them as well.**\n\n**When using autocompletion, component names will be shown with the first path separator.**"
},
"inertia.defaultExtension": {
"type": "string",
"default": ".vue",
Expand All @@ -68,6 +78,9 @@
"workspaceContains:**/*Inertia*",
"onLanguage:php"
],
"dependencies": {
"vscode-uri": "^3.0.7"
},
"devDependencies": {
"@hedger/prettier-config": "^1.2.0",
"@semantic-release/git": "^10.0.1",
Expand Down Expand Up @@ -111,8 +124,5 @@
"preview": true,
"vsce": {
"dependencies": false
},
"dependencies": {
"vscode-uri": "^3.0.7"
}
}
10 changes: 9 additions & 1 deletion src/providers/inertiaComponentAutocompletion.provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ export class InertiaComponentAutocompletionProvider
.getConfiguration('inertia')
.get('pages');

const firstPathSeparator: string | undefined =
workspace
.getConfiguration('inertia')
.get('pathSeparators', ['/'])?.[0] ?? '/';

if (!pagesGlob) {
return undefined;
}
Expand All @@ -61,9 +66,12 @@ export class InertiaComponentAutocompletionProvider
console.log(files);
return files.map((uri) => {
const base = Uri.joinPath(workspaceURI, unglob(pagesGlob));
console.log(pathDiff(base, uri));
return new CompletionItem(
{
label: pathDiff(base, uri).replace(/\.[^/.]+$/, ''),
label: pathDiff(base, uri)
.replace(/\.[^/.]+$/, '')
.replaceAll('/', firstPathSeparator),
description: 'Inertia.js',
},
CompletionItemKind.Value
Expand Down
21 changes: 17 additions & 4 deletions src/providers/inertiaComponentLink.provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class InertiaComponentLinkProvider implements DocumentLinkProvider {
): ProviderResult<DocumentLink[]> {
// https://regex101.com/r/YiSfGR/5
const helperRegex = new RegExp(
'^(?!.*Route::inertia).*inertia\\(\\s*([\'"])(?<component>.+)(\\1)\\s*(?:,[\\s\\S]*?)?\\)',
'^(?!.*Route::inertia).*inertia\\(\\s*([\'"])(?<component>.+)(\\1)\\s*(?:,[\\s\\S]*?)?\\)',
'gdm'
);

Expand Down Expand Up @@ -103,11 +103,13 @@ export class InertiaComponentLinkProvider implements DocumentLinkProvider {
pattern: pages,
})
.then((files) => {
const component = document.getText(link.range);
const path = document.getText(link.range);

const file = files.find((file: Uri) => {
const normalized = this.normalizeComponentPath(path);
console.log(normalized);
return file.path.startsWith(
Uri.joinPath(workspaceURI, unglob(pages), component)
Uri.joinPath(workspaceURI, unglob(pages), normalized)
.path
);
});
Expand All @@ -117,7 +119,7 @@ export class InertiaComponentLinkProvider implements DocumentLinkProvider {
Uri.joinPath(
workspaceURI,
unglob(pages),
component +
path +
workspace
.getConfiguration('inertia')
.get('defaultExtension', '.vue')
Expand All @@ -126,4 +128,15 @@ export class InertiaComponentLinkProvider implements DocumentLinkProvider {
return link;
});
}

private normalizeComponentPath(component: string): string {
const pathSeparators: string[] | undefined = workspace
.getConfiguration('inertia')
.get('pathSeparators', ['/']);

return component.replaceAll(
new RegExp(`[${pathSeparators.join('')}]`, 'g'),
'/'
);
}
}
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"compilerOptions": {
"strict": true,
"target": "ES2020",
"target": "ES2021",
"module": "CommonJS",
"skipLibCheck": true,
"esModuleInterop": true,
Expand Down

0 comments on commit cc9af45

Please sign in to comment.