Skip to content

Commit 0deb95f

Browse files
wip(core)!: remove extname from PathHandlers, then replace PathHandlers with PathResolve
using extname(path) as type is only a default behavior and is now handled in defaultGetResource=>getContent()
1 parent 6a7e722 commit 0deb95f

File tree

4 files changed

+82
-99
lines changed

4 files changed

+82
-99
lines changed

docs/examples.md

Lines changed: 50 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,7 @@ In the following example we use a trick to preserve reactivity through the `Vue.
793793
},
794794
getResource({ refPath, relPath }, options) {
795795
796-
const { moduleCache, pathHandlers: { resolve }, getFile } = options;
796+
const { moduleCache, pathResolve, getFile } = options;
797797
798798
const [ resourceRelPath, ...loaders ] = relPath.match(/([^!]+!)|[^!]+$/g).reverse();
799799
@@ -807,7 +807,7 @@ In the following example we use a trick to preserve reactivity through the `Vue.
807807
}
808808
809809
// get the actual path of the file
810-
const path = resolve({ refPath, relPath: resourceRelPath });
810+
const path = pathResolve({ refPath, relPath: resourceRelPath });
811811
812812
// the resource id must be unique in its path context
813813
const id = loaders.join('') + path;
@@ -855,71 +855,66 @@ This example use Vue2 because **vue-calendar-picker** is written for Vue2.
855855
<div id="app"></div>
856856
<script src="https://unpkg.com/vue@2/dist/vue.js"></script>
857857
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue2-sfc-loader.js"></script>
858-
859858
<script>
860859
861860
const options = {
862861
moduleCache: {
863862
vue: Vue,
864863
'date-fns/locale/en/index.js': {}, // handle require('date-fns/locale/' + this.locale.toLowerCase() + '/index.js');
865864
},
866-
pathHandlers: {
867-
extname(filepath) {
865+
pathResolve({ refPath, relPath }) {
868866
869-
const { pathname } = new URL(filepath, window.location);
870-
return /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/.exec(pathname)[4];
871-
},
872-
resolve({ refPath, relPath }) {
873-
874-
if ( relPath === 'date-fns' )
875-
return 'https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.30.1/date_fns.min.js';
867+
if ( relPath === 'date-fns' )
868+
return 'https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.30.1/date_fns.min.js';
876869
877-
if ( relPath === '.' ) // self
878-
return refPath;
879-
880-
// relPath is a module name ?
881-
if ( relPath[0] !== '.' && relPath[0] !== '/' )
882-
return relPath;
870+
if ( relPath === '.' ) // self
871+
return refPath;
872+
873+
// relPath is a module name ?
874+
if ( relPath[0] !== '.' && relPath[0] !== '/' )
875+
return relPath;
883876
884-
return String(new URL(relPath, refPath === '/' ? window.location : refPath));
885-
}
877+
return String(new URL(relPath, refPath === undefined ? window.location : refPath));
886878
},
887-
async getFile(url) {
888-
879+
getFile: async (url) => {
880+
889881
if ( new URL(url).pathname === '/main.vue' ) {
890-
891-
return /*<!--*/`
892-
<template>
893-
<div>
894-
<calendar-range locale="EN" :selection="selection" :events="calendarEvents"/>
895-
<button @click="add">add</button>
896-
</div>
897-
</template>
898-
<script>
899-
import calendarRange from 'https://raw.githubusercontent.com/FranckFreiburger/vue-calendar-picker/v1.2.1/src/calendarRange.vue'
900-
901-
export default {
902-
components: {
903-
calendarRange,
904-
},
905-
data: {
906-
selection: { start: Date.now(), end: Date.now() },
907-
calendarEvents: []
908-
},
909-
methods: {
910-
add: function() {
911-
this.calendarEvents.push({
912-
color: '#'+Math.floor(Math.random()*16777215).toString(16),
913-
start: this.selection.start,
914-
end: this.selection.end
915-
});
882+
883+
return {
884+
content: /*<!--*/`
885+
<template>
886+
<div>
887+
<calendar-range locale="EN" :selection="selection" :events="calendarEvents"/>
888+
<button @click="add">add</button>
889+
</div>
890+
</template>
891+
<script>
892+
import calendarRange from 'https://raw.githubusercontent.com/FranckFreiburger/vue-calendar-picker/v1.2.1/src/calendarRange.vue'
893+
894+
export default {
895+
components: {
896+
calendarRange,
897+
},
898+
data: {
899+
selection: { start: Date.now(), end: Date.now() },
900+
calendarEvents: []
901+
},
902+
methods: {
903+
add: function() {
904+
this.calendarEvents.push({
905+
color: '#'+Math.floor(Math.random()*16777215).toString(16),
906+
start: this.selection.start,
907+
end: this.selection.end
908+
});
909+
}
916910
}
917911
}
918-
}
919-
</script>
920-
`/* --> */;
912+
</script>
913+
`/* --> */,
914+
type: '.vue',
915+
}
921916
}
922-
917+
923918
return fetch(url).then(res => res.text());
924919
},
925920
addStyle(textContent) {
@@ -929,19 +924,19 @@ This example use Vue2 because **vue-calendar-picker** is written for Vue2.
929924
document.head.insertBefore(style, ref);
930925
},
931926
}
932-
927+
933928
const { loadModule } = window['vue2-sfc-loader'];
934929
935930
loadModule('/main.vue', options)
936931
.then(component => new Vue(component).$mount('#app'))
937-
932+
938933
</script>
939934

940935
</body>
941936
</html>
942937
```
943938
<!--example:target:remote_vue_components-->
944-
[open in JSBin ▶](http://jsbin.com/?html,output&html=%3C!DOCTYPE+html%3E%0A%3Chtml%3E%0A%3Cbody%3E%0A++%3Cdiv+id%3D%22app%22%3E%3C%2Fdiv%3E%0A++%3Cscript+src%3D%22https%3A%2F%2Funpkg.com%2Fvue%402%2Fdist%2Fvue.js%22%3E%3C%2Fscript%3E%0A++%3Cscript+src%3D%22https%3A%2F%2Fcdn.jsdelivr.net%2Fnpm%2Fvue3-sfc-loader%400.6.1%2Fdist%2Fvue2-sfc-loader.js%22%3E%3C%2Fscript%3E%0A+%0A++%3Cscript%3E%0A++++%0A++++const+options+%3D+%7B%0A++++++moduleCache%3A+%7B%0A++++++++vue%3A+Vue%2C%0A++++++++'date-fns%2Flocale%2Fen%2Findex.js'%3A+%7B%7D%2C+%2F%2F+handle+require('date-fns%2Flocale%2F'+%2B+this.locale.toLowerCase()+%2B+'%2Findex.js')%3B%0A++++++%7D%2C%0A++++++pathHandlers%3A+%7B%0A++++++++type(filepath)+%7B%0A%0A++++++++++const+%7B+pathname+%7D+%3D+new+URL(filepath%2C+window.location)%3B%0A++++++++++return+%2F%5E(%5C%2F%3F%7C)(%5B%5Cs%5CS%5D*%3F)((%3F%3A%5C.%7B1%2C2%7D%7C%5B%5E%5C%2F%5D%2B%3F%7C)(%5C.%5B%5E.%5C%2F%5D*%7C))(%3F%3A%5B%5C%2F%5D*)%24%2F.exec(pathname)%5B4%5D%3B%0A++++++++%7D%2C%0A++++++++resolve(%7B+refPath%2C+relPath+%7D)+%7B%0A%0A++++++++++if+(+relPath+%3D%3D%3D+'date-fns'+)%0A++++++++++++return+'https%3A%2F%2Fcdnjs.cloudflare.com%2Fajax%2Flibs%2Fdate-fns%2F1.30.1%2Fdate_fns.min.js'%3B%0A%0A++++++++++if+(+relPath+%3D%3D%3D+'.'+)+%2F%2F+self%0A++++++++++++return+refPath%3B%0A++++++++++%0A++++++++++%2F%2F+relPath+is+a+module+name+%3F%0A++++++++++if+(+relPath%5B0%5D+!%3D%3D+'.'+%26%26+relPath%5B0%5D+!%3D%3D+'%2F'+)%0A++++++++++++return+relPath%3B%0A%0A++++++++++return+String(new+URL(relPath%2C+refPath+%3D%3D%3D+'%2F'+%3F+window.location+%3A+refPath))%3B%0A++++++++%7D%0A++++++%7D%2C%0A++++++async+getFile(url)+%7B%0A++%0A++++++++if+(+new+URL(url).pathname+%3D%3D%3D+'%2Fmain.vue'+)+%7B%0A++%0A++++++++++return+%2F*%3C!--*%2F%60%0A++++++++++++%3Ctemplate%3E%0A++++++++++++++%3Cdiv%3E%0A++++++++++++++++%3Ccalendar-range+locale%3D%22EN%22+%3Aselection%3D%22selection%22+%3Aevents%3D%22calendarEvents%22%2F%3E%0A++++++++++++++++%3Cbutton+%40click%3D%22add%22%3Eadd%3C%2Fbutton%3E%0A++++++++++++++%3C%2Fdiv%3E%0A++++++++++++%3C%2Ftemplate%3E%0A++++++++++++%3Cscript%3E%0A++++++++++++++import+calendarRange+from+'https%3A%2F%2Fraw.githubusercontent.com%2FFranckFreiburger%2Fvue-calendar-picker%2Fv1.2.1%2Fsrc%2FcalendarRange.vue'%0A%0A++++++++++++++export+default+%7B%0A++++++++++++++++components%3A+%7B%0A++++++++++++++++++calendarRange%2C%0A++++++++++++++++%7D%2C%0A++++++++++++++++data%3A+%7B%0A++++++++++++++++++selection%3A+%7B+start%3A+Date.now()%2C+end%3A+Date.now()+%7D%2C%0A++++++++++++++++++calendarEvents%3A+%5B%5D%0A++++++++++++++++%7D%2C%0A++++++++++++++++methods%3A+%7B%0A++++++++++++++++++add%3A+function()+%7B%0A++++++++++++++++++++this.calendarEvents.push(%7B%0A++++++++++++++++++++++color%3A+'%23'%2BMath.floor(Math.random()*16777215).toString(16)%2C%0A++++++++++++++++++++++start%3A+this.selection.start%2C%0A++++++++++++++++++++++end%3A+this.selection.end%0A++++++++++++++++++++%7D)%3B%0A++++++++++++++++++%7D%0A++++++++++++++++%7D%0A++++++++++++++%7D%0A++++++++++++%3C%2Fscript%3E%0A++++++++++%60%2F*+--%3E+*%2F%3B%0A++++++++%7D%0A++%0A++++++++return+fetch(url).then(res+%3D%3E+res.text())%3B%0A++++++%7D%2C%0A++++++addStyle(textContent)+%7B%0A%0A++++++++const+style+%3D+Object.assign(document.createElement('style')%2C+%7B+textContent+%7D)%3B%0A++++++++const+ref+%3D+document.head.getElementsByTagName('style')%5B0%5D+%7C%7C+null%3B%0A++++++++document.head.insertBefore(style%2C+ref)%3B%0A++++++%7D%2C%0A++++%7D%0A++%0A++++const+%7B+loadModule+%7D+%3D+window%5B'vue2-sfc-loader'%5D%3B%0A%0A++++loadModule('%2Fmain.vue'%2C+options)%0A++++.then(component+%3D%3E+new+Vue(component).%24mount('%23app'))%0A++%0A++%3C%2Fscript%3E%0A%0A%3C%2Fbody%3E%0A%3C%2Fhtml%3E%0A)<!--/example:target:remote_vue_components-->
939+
<!--/example:target:remote_vue_components-->
945940

946941
[:top:](#readme)
947942

src/index.ts

Lines changed: 27 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88

99
import {
1010
ModuleExport,
11-
PathHandlers,
11+
PathResolve,
1212
Options,
1313
File,
1414
Resource,
@@ -41,46 +41,47 @@ function throwNotDefined(details : string) : never {
4141

4242

4343
/**
44-
* Default implementation of PathHandlers.
44+
* Default resolve implementation
4545
* resolve() should handle 3 situations :
4646
* - resolve a relative path ( eg. import './details.vue' )
4747
* - resolve an absolute path ( eg. import '/components/card.vue' )
4848
* - resolve a module name ( eg. import { format } from 'date-fns' )
4949
*/
50-
const defaultPathHandlers : PathHandlers = {
51-
extname(filepath) {
50+
const defaultPathResolve : PathResolve = ({ refPath, relPath } : PathContext) => {
5251

53-
return Path.extname(filepath.toString());
54-
},
55-
resolve({ refPath, relPath } : PathContext) {
52+
// initial resolution: refPath is not defined
53+
if ( refPath === undefined )
54+
return relPath;
5655

57-
// initial resolution: refPath is not defined
58-
if ( refPath === undefined )
59-
return relPath;
56+
// note :
57+
// normalize('./test') -> 'test'
58+
// normalize('/test') -> '/test'
6059

61-
// note :
62-
// normalize('./test') -> 'test'
63-
// normalize('/test') -> '/test'
60+
const relPathStr = relPath.toString();
6461

65-
const relPathStr = relPath.toString();
62+
// a module name ?
63+
if ( relPathStr[0] !== '.' && relPathStr[0] !== '/' )
64+
return relPath;
6665

67-
// a module name ?
68-
if ( relPathStr[0] !== '.' && relPathStr[0] !== '/' )
69-
return relPath;
70-
71-
return Path.normalize(Path.join(Path.dirname(refPath.toString()), relPathStr));
72-
}
66+
return Path.normalize(Path.join(Path.dirname(refPath.toString()), relPathStr));
7367
}
7468

75-
69+
/**
70+
* Default getResource implementation
71+
* by default, getContent() use the file extension as file type.
72+
*/
7673
function defaultGetResource(pathCx : PathContext, options : Options) : Resource {
7774

78-
const { pathHandlers: { resolve }, getFile } = options;
79-
const path = resolve(pathCx);
75+
const { pathResolve, getFile } = options;
76+
const path = pathResolve(pathCx);
8077
return {
8178
id: path.toString(),
8279
path: path,
83-
getContent: () => getFile(path),
80+
getContent: async () => {
81+
82+
const res = await getFile(path);
83+
return typeof res === 'object' ? res : { content: res, type: Path.extname(path.toString()) };
84+
}
8485
};
8586
}
8687

@@ -132,27 +133,19 @@ export async function loadModule(path : AbstractPath, options : Options = throwN
132133
moduleCache = throwNotDefined('options.moduleCache'),
133134
getFile = throwNotDefined('options.getFile()'),
134135
addStyle = throwNotDefined('options.addStyle()'),
135-
pathHandlers = defaultPathHandlers,
136+
pathResolve = defaultPathResolve,
136137
getResource = defaultGetResource,
137138
} = options;
138139

139140
// moduleCache should be defined with Object.create(null). require('constructor') etc... should not be a default module
140141
if ( moduleCache instanceof Object )
141142
Object.setPrototypeOf(moduleCache, null);
142143

143-
// TBD: remove this in v1.0
144-
async function normalizedGetFile(path : AbstractPath) : Promise<File> {
145-
146-
const res = await getFile(path);
147-
return typeof res === 'object' ? res : { content: res, type: pathHandlers.extname(path) };
148-
}
149-
150144
const normalizedOptions = {
151145
moduleCache,
152-
pathHandlers,
146+
pathResolve,
153147
getResource,
154148
...options,
155-
getFile: normalizedGetFile,
156149
};
157150

158151
return await loadModuleInternal( { refPath: undefined, relPath: path }, normalizedOptions);

src/tools.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ export async function loadModuleInternal(pathCx : PathContext, options : Options
309309
*/
310310
export function createModule(refPath : AbstractPath, source : string, options : Options) : Module {
311311

312-
const { moduleCache, pathHandlers: { resolve }, getResource } = options;
312+
const { moduleCache, pathResolve, getResource } = options;
313313

314314
const require = function(relPath : string) {
315315

@@ -331,7 +331,7 @@ export function createModule(refPath : AbstractPath, source : string, options :
331331

332332
// see https://github.com/nodejs/node/blob/a46b21f556a83e43965897088778ddc7d46019ae/lib/internal/modules/cjs/loader.js#L195-L198
333333
// see https://github.com/nodejs/node/blob/a46b21f556a83e43965897088778ddc7d46019ae/lib/internal/modules/cjs/loader.js#L1102
334-
Function('exports', 'require', 'module', '__filename', '__dirname', 'import__', source).call(module.exports, module.exports, require, module, refPath, resolve({ refPath, relPath: '.' }), importFunction);
334+
Function('exports', 'require', 'module', '__filename', '__dirname', 'import__', source).call(module.exports, module.exports, require, module, refPath, pathResolve({ refPath, relPath: '.' }), importFunction);
335335

336336
return module;
337337
}

src/types.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,8 @@ export type PathContext = {
3535
}
3636

3737

38-
export type PathHandlers = {
39-
/** the extension name (or type) of a file (incluting the leading dot, eg. '.svg') */
40-
extname(filepath : AbstractPath) : string,
41-
/** relative to absolute module path resolution */
42-
resolve(pathCx : PathContext) : AbstractPath,
43-
}
44-
38+
/** relative to absolute module path resolution */
39+
export type PathResolve = (pathCx : PathContext) => AbstractPath;
4540

4641

4742
/**
@@ -335,7 +330,7 @@ export type Options = {
335330
* Abstact path handling
336331
*
337332
*/
338-
pathHandlers : PathHandlers,
333+
pathResolve : PathResolve,
339334

340335

341336
/**

0 commit comments

Comments
 (0)