@speclynx/apidom-reference 5.2.7 → 6.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@speclynx/apidom-reference",
3
- "version": "5.2.7",
3
+ "version": "6.0.1",
4
4
  "description": "Advanced algorithms for semantic ApiDOM manipulations like dereferencing or resolution.",
5
5
  "keywords": [
6
6
  "apidom",
@@ -299,32 +299,32 @@
299
299
  "license": "Apache-2.0",
300
300
  "dependencies": {
301
301
  "@babel/runtime-corejs3": "^8.0.5",
302
- "@speclynx/apidom-core": "5.2.7",
303
- "@speclynx/apidom-datamodel": "5.2.7",
304
- "@speclynx/apidom-error": "5.2.7",
305
- "@speclynx/apidom-json-pointer": "5.2.7",
306
- "@speclynx/apidom-ns-arazzo-1": "5.2.7",
307
- "@speclynx/apidom-ns-asyncapi-2": "5.2.7",
308
- "@speclynx/apidom-ns-json-schema-2020-12": "5.2.7",
309
- "@speclynx/apidom-ns-openapi-2": "5.2.7",
310
- "@speclynx/apidom-ns-openapi-3-0": "5.2.7",
311
- "@speclynx/apidom-ns-openapi-3-1": "5.2.7",
312
- "@speclynx/apidom-ns-overlay-1": "5.2.7",
313
- "@speclynx/apidom-parser-adapter-arazzo-json-1": "5.2.7",
314
- "@speclynx/apidom-parser-adapter-arazzo-yaml-1": "5.2.7",
315
- "@speclynx/apidom-parser-adapter-asyncapi-json-2": "5.2.7",
316
- "@speclynx/apidom-parser-adapter-asyncapi-yaml-2": "5.2.7",
317
- "@speclynx/apidom-parser-adapter-json": "5.2.7",
318
- "@speclynx/apidom-parser-adapter-openapi-json-2": "5.2.7",
319
- "@speclynx/apidom-parser-adapter-openapi-json-3-0": "5.2.7",
320
- "@speclynx/apidom-parser-adapter-openapi-json-3-1": "5.2.7",
321
- "@speclynx/apidom-parser-adapter-openapi-yaml-2": "5.2.7",
322
- "@speclynx/apidom-parser-adapter-openapi-yaml-3-0": "5.2.7",
323
- "@speclynx/apidom-parser-adapter-openapi-yaml-3-1": "5.2.7",
324
- "@speclynx/apidom-parser-adapter-overlay-json-1": "5.2.7",
325
- "@speclynx/apidom-parser-adapter-overlay-yaml-1": "5.2.7",
326
- "@speclynx/apidom-parser-adapter-yaml-1-2": "5.2.7",
327
- "@speclynx/apidom-traverse": "5.2.7",
302
+ "@speclynx/apidom-core": "6.0.1",
303
+ "@speclynx/apidom-datamodel": "6.0.1",
304
+ "@speclynx/apidom-error": "6.0.1",
305
+ "@speclynx/apidom-json-pointer": "6.0.1",
306
+ "@speclynx/apidom-ns-arazzo-1": "6.0.1",
307
+ "@speclynx/apidom-ns-asyncapi-2": "6.0.1",
308
+ "@speclynx/apidom-ns-json-schema-2020-12": "6.0.1",
309
+ "@speclynx/apidom-ns-openapi-2": "6.0.1",
310
+ "@speclynx/apidom-ns-openapi-3-0": "6.0.1",
311
+ "@speclynx/apidom-ns-openapi-3-1": "6.0.1",
312
+ "@speclynx/apidom-ns-overlay-1": "6.0.1",
313
+ "@speclynx/apidom-parser-adapter-arazzo-json-1": "6.0.1",
314
+ "@speclynx/apidom-parser-adapter-arazzo-yaml-1": "6.0.1",
315
+ "@speclynx/apidom-parser-adapter-asyncapi-json-2": "6.0.1",
316
+ "@speclynx/apidom-parser-adapter-asyncapi-yaml-2": "6.0.1",
317
+ "@speclynx/apidom-parser-adapter-json": "6.0.1",
318
+ "@speclynx/apidom-parser-adapter-openapi-json-2": "6.0.1",
319
+ "@speclynx/apidom-parser-adapter-openapi-json-3-0": "6.0.1",
320
+ "@speclynx/apidom-parser-adapter-openapi-json-3-1": "6.0.1",
321
+ "@speclynx/apidom-parser-adapter-openapi-yaml-2": "6.0.1",
322
+ "@speclynx/apidom-parser-adapter-openapi-yaml-3-0": "6.0.1",
323
+ "@speclynx/apidom-parser-adapter-openapi-yaml-3-1": "6.0.1",
324
+ "@speclynx/apidom-parser-adapter-overlay-json-1": "6.0.1",
325
+ "@speclynx/apidom-parser-adapter-overlay-yaml-1": "6.0.1",
326
+ "@speclynx/apidom-parser-adapter-yaml-1-2": "6.0.1",
327
+ "@speclynx/apidom-traverse": "6.0.1",
328
328
  "@swaggerexpert/arazzo-runtime-expression": "^3.2.0",
329
329
  "axios": "^1.20.0",
330
330
  "picomatch": "^4.0.7",
@@ -345,5 +345,5 @@
345
345
  "README.md",
346
346
  "CHANGELOG.md"
347
347
  ],
348
- "gitHead": "e99285824ceb947024c97a13c7827843efdaa9e0"
348
+ "gitHead": "d2ea4f01cac54a0d5e1030386e3b0b60664c9619"
349
349
  }
@@ -45,8 +45,12 @@ async function dereferenceExtends(parseResult, parseResultRetrievalURI, options)
45
45
  if (!(0, _apidomDatamodel.isStringElement)(extendsElement)) {
46
46
  return;
47
47
  }
48
+
49
+ // Overlay 1.2.0: `$self` (itself resolved against the retrieval URI) is the base URI
50
+ const selfElement = api.get('$self');
51
+ const baseURI = (0, _apidomDatamodel.isStringElement)(selfElement) ? url.resolve(file.uri, (0, _apidomCore.toValue)(selfElement)) : file.uri;
48
52
  const extendsURI = (0, _apidomCore.toValue)(extendsElement);
49
- const retrievalURI = url.sanitize(url.stripHash(url.resolve(file.uri, extendsURI)));
53
+ const retrievalURI = url.sanitize(url.stripHash(url.resolve(baseURI, extendsURI)));
50
54
  const extendsDereferenceResult = new _apidomDatamodel.ParseResultElement();
51
55
  extendsDereferenceResult.classes.push('extends');
52
56
  extendsDereferenceResult.setMetaProperty('retrievalURI', retrievalURI);
@@ -37,8 +37,12 @@ export async function dereferenceExtends(parseResult, parseResultRetrievalURI, o
37
37
  if (!isStringElement(extendsElement)) {
38
38
  return;
39
39
  }
40
+
41
+ // Overlay 1.2.0: `$self` (itself resolved against the retrieval URI) is the base URI
42
+ const selfElement = api.get('$self');
43
+ const baseURI = isStringElement(selfElement) ? url.resolve(file.uri, toValue(selfElement)) : file.uri;
40
44
  const extendsURI = toValue(extendsElement);
41
- const retrievalURI = url.sanitize(url.stripHash(url.resolve(file.uri, extendsURI)));
45
+ const retrievalURI = url.sanitize(url.stripHash(url.resolve(baseURI, extendsURI)));
42
46
  const extendsDereferenceResult = new ParseResultElement();
43
47
  extendsDereferenceResult.classes.push('extends');
44
48
  extendsDereferenceResult.setMetaProperty('retrievalURI', retrievalURI);
@@ -4,6 +4,12 @@ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequ
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
+ Object.defineProperty(exports, "Overlay1DereferenceVisitor", {
8
+ enumerable: true,
9
+ get: function () {
10
+ return _visitor.default;
11
+ }
12
+ });
7
13
  exports.default = void 0;
8
14
  Object.defineProperty(exports, "dereferenceExtends", {
9
15
  enumerable: true,
@@ -13,10 +19,12 @@ Object.defineProperty(exports, "dereferenceExtends", {
13
19
  });
14
20
  var _apidomDatamodel = require("@speclynx/apidom-datamodel");
15
21
  var _apidomNsOverlay = require("@speclynx/apidom-ns-overlay-1");
22
+ var _apidomTraverse = require("@speclynx/apidom-traverse");
16
23
  var _DereferenceStrategy = _interopRequireDefault(require("../DereferenceStrategy.cjs"));
17
24
  var _Reference = _interopRequireDefault(require("../../../Reference.cjs"));
18
25
  var _ReferenceSet = _interopRequireDefault(require("../../../ReferenceSet.cjs"));
19
26
  var _extends = require("./extends.cjs");
27
+ var _visitor = _interopRequireDefault(require("./visitor.cjs"));
20
28
  /**
21
29
  * @public
22
30
  */
@@ -68,6 +76,18 @@ class Overlay1DereferenceStrategy extends _DereferenceStrategy.default {
68
76
  }
69
77
  const dereferencedElement = reference.value;
70
78
 
79
+ /**
80
+ * Reusable Action References only occur within `actions`, so the root element is never
81
+ * replaced and traversing it keeps reported locations relative to the document.
82
+ */
83
+ const visitor = new _visitor.default({
84
+ reference,
85
+ options
86
+ });
87
+ await (0, _apidomTraverse.traverseAsync)(dereferencedElement.result, visitor, {
88
+ mutable: true
89
+ });
90
+
71
91
  /**
72
92
  * Dereference extends target if option is enabled.
73
93
  */
@@ -1,9 +1,11 @@
1
1
  import { cloneDeep } from '@speclynx/apidom-datamodel';
2
2
  import { isOverlay1Element, mediaTypes } from '@speclynx/apidom-ns-overlay-1';
3
+ import { traverseAsync } from '@speclynx/apidom-traverse';
3
4
  import DereferenceStrategy from "../DereferenceStrategy.mjs";
4
5
  import Reference from "../../../Reference.mjs";
5
6
  import ReferenceSet from "../../../ReferenceSet.mjs";
6
7
  import { dereferenceExtends } from "./extends.mjs";
8
+ import Overlay1DereferenceVisitor from "./visitor.mjs";
7
9
  /**
8
10
  * @public
9
11
  */
@@ -54,6 +56,18 @@ class Overlay1DereferenceStrategy extends DereferenceStrategy {
54
56
  }
55
57
  const dereferencedElement = reference.value;
56
58
 
59
+ /**
60
+ * Reusable Action References only occur within `actions`, so the root element is never
61
+ * replaced and traversing it keeps reported locations relative to the document.
62
+ */
63
+ const visitor = new Overlay1DereferenceVisitor({
64
+ reference,
65
+ options
66
+ });
67
+ await traverseAsync(dereferencedElement.result, visitor, {
68
+ mutable: true
69
+ });
70
+
57
71
  /**
58
72
  * Dereference extends target if option is enabled.
59
73
  */
@@ -84,4 +98,5 @@ class Overlay1DereferenceStrategy extends DereferenceStrategy {
84
98
  }
85
99
  }
86
100
  export { dereferenceExtends } from "./extends.mjs";
101
+ export { Overlay1DereferenceVisitor };
87
102
  export default Overlay1DereferenceStrategy;
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = void 0;
8
+ var _apidomDatamodel = require("@speclynx/apidom-datamodel");
9
+ var _apidomCore = require("@speclynx/apidom-core");
10
+ var _apidomError = require("@speclynx/apidom-error");
11
+ var _apidomJsonPointer = require("@speclynx/apidom-json-pointer");
12
+ var _apidomNsOverlay = require("@speclynx/apidom-ns-overlay-1");
13
+ var _UnresolvableReferenceError = _interopRequireDefault(require("../../../errors/UnresolvableReferenceError.cjs"));
14
+ /**
15
+ * @public
16
+ */
17
+
18
+ /**
19
+ * @public
20
+ */
21
+ class Overlay1DereferenceVisitor {
22
+ reference;
23
+ options;
24
+ constructor({
25
+ reference,
26
+ options
27
+ }) {
28
+ this.reference = reference;
29
+ this.options = options;
30
+ }
31
+ ReusableActionReferenceElement(path) {
32
+ const referencingElement = path.node;
33
+
34
+ // ignore if resolve.internal is false (Reusable Action References are internal references only)
35
+ if (!this.options.resolve.internal) {
36
+ path.skip();
37
+ return;
38
+ }
39
+ const $ref = (0, _apidomCore.toValue)(referencingElement.$ref);
40
+ const overlayElement = this.reference.value.result;
41
+ const actionElement = new _apidomNsOverlay.ActionElement();
42
+ try {
43
+ if (typeof $ref !== 'string') {
44
+ throw new _apidomError.ApiDOMStructuredError('Reusable Action Reference "$ref" field must be a string');
45
+ }
46
+
47
+ // only `target`, `description` and extensions may accompany `$ref`
48
+ const disallowedField = ['update', 'copy', 'remove'].find(field => referencingElement.hasKey(field));
49
+ if (disallowedField !== undefined) {
50
+ throw new _apidomError.ApiDOMStructuredError(`Reusable Action Reference "${$ref}" must not define "${disallowedField}"`, {
51
+ $ref
52
+ });
53
+ }
54
+
55
+ // same-document reference only; external references are not supported
56
+ if (!$ref.startsWith('#')) {
57
+ throw new _apidomError.ApiDOMStructuredError(`Reusable Action Reference "${$ref}" must be a same-document reference`, {
58
+ $ref
59
+ });
60
+ }
61
+
62
+ /**
63
+ * Only entries of `components.actions` are refracted as Reusable Actions,
64
+ * so the element type alone proves the pointer leads there.
65
+ */
66
+ let reusableAction;
67
+ try {
68
+ reusableAction = (0, _apidomJsonPointer.evaluate)(overlayElement, _apidomJsonPointer.URIFragmentIdentifier.from($ref));
69
+ } catch {
70
+ reusableAction = undefined;
71
+ }
72
+ if (!(0, _apidomNsOverlay.isReusableActionElement)(reusableAction)) {
73
+ throw new _apidomError.ApiDOMStructuredError(`Reusable Action Reference "${$ref}" cannot be resolved`, {
74
+ $ref
75
+ });
76
+ }
77
+ const {
78
+ fields
79
+ } = reusableAction;
80
+ if (fields !== undefined && !(0, _apidomNsOverlay.isActionElement)(fields)) {
81
+ throw new _apidomError.ApiDOMStructuredError(`Reusable Action "${$ref}" must define "fields" as an object`, {
82
+ $ref
83
+ });
84
+ }
85
+ if ((0, _apidomNsOverlay.isActionElement)(fields) && fields.hasKey('target')) {
86
+ throw new _apidomError.ApiDOMStructuredError(`Reusable Action "${$ref}" must not define "target" in its "fields"`, {
87
+ $ref
88
+ });
89
+ }
90
+
91
+ // the reference supplies `target` and its `description` takes precedence over the one in `fields`
92
+ const {
93
+ target,
94
+ description
95
+ } = referencingElement;
96
+ if (target !== undefined) {
97
+ actionElement.set('target', (0, _apidomDatamodel.cloneDeep)(target));
98
+ }
99
+ if ((0, _apidomNsOverlay.isActionElement)(fields)) {
100
+ fields.forEach((value, keyElement) => {
101
+ actionElement.set((0, _apidomCore.toValue)(keyElement), (0, _apidomDatamodel.cloneDeep)(value));
102
+ });
103
+ }
104
+ if (description !== undefined) {
105
+ actionElement.set('description', (0, _apidomDatamodel.cloneDeep)(description));
106
+ }
107
+ } catch (error) {
108
+ const {
109
+ continueOnError
110
+ } = this.options.dereference;
111
+ const unresolvedError = new _UnresolvableReferenceError.default(`Error while dereferencing Reusable Action Reference "${$ref}": ${error.message}`, {
112
+ cause: error,
113
+ type: referencingElement.element,
114
+ uri: this.reference.uri,
115
+ location: path.formatPath(),
116
+ codeFrame: (0, _apidomCore.toYAML)(referencingElement),
117
+ refFieldName: '$ref',
118
+ refFieldValue: $ref,
119
+ trace: []
120
+ });
121
+ if (continueOnError === false) throw unresolvedError;
122
+ if (typeof continueOnError === 'function') continueOnError(unresolvedError);
123
+ path.skip();
124
+ return;
125
+ }
126
+
127
+ // the action takes the place of the reference in `actions`, so it inherits its source position
128
+ if ((0, _apidomDatamodel.hasElementSourceMap)(referencingElement)) {
129
+ _apidomDatamodel.SourceMapElement.transfer(referencingElement, actionElement);
130
+ }
131
+
132
+ // annotate with info about original referencing element
133
+ actionElement.meta.set('ref-fields', {
134
+ $ref,
135
+ description: (0, _apidomCore.toValue)(referencingElement.description)
136
+ });
137
+ // annotate with info about origin
138
+ actionElement.meta.set('ref-origin', this.reference.uri);
139
+ actionElement.meta.set('ref-type', referencingElement.element);
140
+
141
+ /**
142
+ * Transclude referencing element with resolved Action Object.
143
+ */
144
+ path.replaceWith(actionElement);
145
+ path.skip();
146
+ }
147
+ }
148
+ var _default = exports.default = Overlay1DereferenceVisitor;
@@ -0,0 +1,140 @@
1
+ import { SourceMapElement, cloneDeep, hasElementSourceMap } from '@speclynx/apidom-datamodel';
2
+ import { toValue, toYAML } from '@speclynx/apidom-core';
3
+ import { ApiDOMStructuredError } from '@speclynx/apidom-error';
4
+ import { evaluate as jsonPointerEvaluate, URIFragmentIdentifier } from '@speclynx/apidom-json-pointer';
5
+ import { ActionElement, isActionElement, isReusableActionElement } from '@speclynx/apidom-ns-overlay-1';
6
+ import UnresolvableReferenceError from "../../../errors/UnresolvableReferenceError.mjs";
7
+ /**
8
+ * @public
9
+ */
10
+ /**
11
+ * @public
12
+ */
13
+ class Overlay1DereferenceVisitor {
14
+ reference;
15
+ options;
16
+ constructor({
17
+ reference,
18
+ options
19
+ }) {
20
+ this.reference = reference;
21
+ this.options = options;
22
+ }
23
+ ReusableActionReferenceElement(path) {
24
+ const referencingElement = path.node;
25
+
26
+ // ignore if resolve.internal is false (Reusable Action References are internal references only)
27
+ if (!this.options.resolve.internal) {
28
+ path.skip();
29
+ return;
30
+ }
31
+ const $ref = toValue(referencingElement.$ref);
32
+ const overlayElement = this.reference.value.result;
33
+ const actionElement = new ActionElement();
34
+ try {
35
+ if (typeof $ref !== 'string') {
36
+ throw new ApiDOMStructuredError('Reusable Action Reference "$ref" field must be a string');
37
+ }
38
+
39
+ // only `target`, `description` and extensions may accompany `$ref`
40
+ const disallowedField = ['update', 'copy', 'remove'].find(field => referencingElement.hasKey(field));
41
+ if (disallowedField !== undefined) {
42
+ throw new ApiDOMStructuredError(`Reusable Action Reference "${$ref}" must not define "${disallowedField}"`, {
43
+ $ref
44
+ });
45
+ }
46
+
47
+ // same-document reference only; external references are not supported
48
+ if (!$ref.startsWith('#')) {
49
+ throw new ApiDOMStructuredError(`Reusable Action Reference "${$ref}" must be a same-document reference`, {
50
+ $ref
51
+ });
52
+ }
53
+
54
+ /**
55
+ * Only entries of `components.actions` are refracted as Reusable Actions,
56
+ * so the element type alone proves the pointer leads there.
57
+ */
58
+ let reusableAction;
59
+ try {
60
+ reusableAction = jsonPointerEvaluate(overlayElement, URIFragmentIdentifier.from($ref));
61
+ } catch {
62
+ reusableAction = undefined;
63
+ }
64
+ if (!isReusableActionElement(reusableAction)) {
65
+ throw new ApiDOMStructuredError(`Reusable Action Reference "${$ref}" cannot be resolved`, {
66
+ $ref
67
+ });
68
+ }
69
+ const {
70
+ fields
71
+ } = reusableAction;
72
+ if (fields !== undefined && !isActionElement(fields)) {
73
+ throw new ApiDOMStructuredError(`Reusable Action "${$ref}" must define "fields" as an object`, {
74
+ $ref
75
+ });
76
+ }
77
+ if (isActionElement(fields) && fields.hasKey('target')) {
78
+ throw new ApiDOMStructuredError(`Reusable Action "${$ref}" must not define "target" in its "fields"`, {
79
+ $ref
80
+ });
81
+ }
82
+
83
+ // the reference supplies `target` and its `description` takes precedence over the one in `fields`
84
+ const {
85
+ target,
86
+ description
87
+ } = referencingElement;
88
+ if (target !== undefined) {
89
+ actionElement.set('target', cloneDeep(target));
90
+ }
91
+ if (isActionElement(fields)) {
92
+ fields.forEach((value, keyElement) => {
93
+ actionElement.set(toValue(keyElement), cloneDeep(value));
94
+ });
95
+ }
96
+ if (description !== undefined) {
97
+ actionElement.set('description', cloneDeep(description));
98
+ }
99
+ } catch (error) {
100
+ const {
101
+ continueOnError
102
+ } = this.options.dereference;
103
+ const unresolvedError = new UnresolvableReferenceError(`Error while dereferencing Reusable Action Reference "${$ref}": ${error.message}`, {
104
+ cause: error,
105
+ type: referencingElement.element,
106
+ uri: this.reference.uri,
107
+ location: path.formatPath(),
108
+ codeFrame: toYAML(referencingElement),
109
+ refFieldName: '$ref',
110
+ refFieldValue: $ref,
111
+ trace: []
112
+ });
113
+ if (continueOnError === false) throw unresolvedError;
114
+ if (typeof continueOnError === 'function') continueOnError(unresolvedError);
115
+ path.skip();
116
+ return;
117
+ }
118
+
119
+ // the action takes the place of the reference in `actions`, so it inherits its source position
120
+ if (hasElementSourceMap(referencingElement)) {
121
+ SourceMapElement.transfer(referencingElement, actionElement);
122
+ }
123
+
124
+ // annotate with info about original referencing element
125
+ actionElement.meta.set('ref-fields', {
126
+ $ref,
127
+ description: toValue(referencingElement.description)
128
+ });
129
+ // annotate with info about origin
130
+ actionElement.meta.set('ref-origin', this.reference.uri);
131
+ actionElement.meta.set('ref-type', referencingElement.element);
132
+
133
+ /**
134
+ * Transclude referencing element with resolved Action Object.
135
+ */
136
+ path.replaceWith(actionElement);
137
+ path.skip();
138
+ }
139
+ }
140
+ export default Overlay1DereferenceVisitor;
@@ -40,8 +40,12 @@ async function parseExtends(parseResult, parseResultRetrievalURI, options) {
40
40
  if (!(0, _apidomDatamodel.isStringElement)(extendsElement)) {
41
41
  return;
42
42
  }
43
+
44
+ // Overlay 1.2.0: `$self` (itself resolved against the retrieval URI) is the base URI
45
+ const selfElement = api.get('$self');
46
+ const baseURI = (0, _apidomDatamodel.isStringElement)(selfElement) ? url.resolve(file.uri, (0, _apidomCore.toValue)(selfElement)) : file.uri;
43
47
  const extendsURI = (0, _apidomCore.toValue)(extendsElement);
44
- const retrievalURI = url.sanitize(url.stripHash(url.resolve(file.uri, extendsURI)));
48
+ const retrievalURI = url.sanitize(url.stripHash(url.resolve(baseURI, extendsURI)));
45
49
  const extendsParseResult = new _apidomDatamodel.ParseResultElement();
46
50
  extendsParseResult.classes.push('extends');
47
51
  extendsParseResult.setMetaProperty('retrievalURI', retrievalURI);
@@ -32,8 +32,12 @@ export async function parseExtends(parseResult, parseResultRetrievalURI, options
32
32
  if (!isStringElement(extendsElement)) {
33
33
  return;
34
34
  }
35
+
36
+ // Overlay 1.2.0: `$self` (itself resolved against the retrieval URI) is the base URI
37
+ const selfElement = api.get('$self');
38
+ const baseURI = isStringElement(selfElement) ? url.resolve(file.uri, toValue(selfElement)) : file.uri;
35
39
  const extendsURI = toValue(extendsElement);
36
- const retrievalURI = url.sanitize(url.stripHash(url.resolve(file.uri, extendsURI)));
40
+ const retrievalURI = url.sanitize(url.stripHash(url.resolve(baseURI, extendsURI)));
37
41
  const extendsParseResult = new ParseResultElement();
38
42
  extendsParseResult.classes.push('extends');
39
43
  extendsParseResult.setMetaProperty('retrievalURI', retrievalURI);
package/src/util/url.cjs CHANGED
@@ -266,13 +266,14 @@ exports.cwd = cwd;
266
266
  const resolve = (from, to) => {
267
267
  const resolvedUrl = new URL(to, new URL(from, 'resolve://'));
268
268
  if (resolvedUrl.protocol === 'resolve:') {
269
- // `from` is a relative URL.
269
+ // `from` is a relative URL; a network-path reference (`//host/path`) keeps its authority
270
270
  const {
271
+ host,
271
272
  pathname,
272
273
  search,
273
274
  hash
274
275
  } = resolvedUrl;
275
- return pathname + search + hash;
276
+ return (host ? `//${host}` : '') + pathname + search + hash;
276
277
  }
277
278
  return resolvedUrl.toString();
278
279
  };
package/src/util/url.mjs CHANGED
@@ -251,13 +251,14 @@ export const cwd = () => {
251
251
  export const resolve = (from, to) => {
252
252
  const resolvedUrl = new URL(to, new URL(from, 'resolve://'));
253
253
  if (resolvedUrl.protocol === 'resolve:') {
254
- // `from` is a relative URL.
254
+ // `from` is a relative URL; a network-path reference (`//host/path`) keeps its authority
255
255
  const {
256
+ host,
256
257
  pathname,
257
258
  search,
258
259
  hash
259
260
  } = resolvedUrl;
260
- return pathname + search + hash;
261
+ return (host ? `//${host}` : '') + pathname + search + hash;
261
262
  }
262
263
  return resolvedUrl.toString();
263
264
  };
@@ -2,6 +2,7 @@ import { Element } from '@speclynx/apidom-datamodel';
2
2
  import DereferenceStrategy, { DereferenceStrategyOptions } from '../DereferenceStrategy.ts';
3
3
  import File from '../../../File.ts';
4
4
  import type { ReferenceOptions } from '../../../options/index.ts';
5
+ import Overlay1DereferenceVisitor from './visitor.ts';
5
6
  export type { default as DereferenceStrategy, DereferenceStrategyOptions, } from '../DereferenceStrategy.ts';
6
7
  export type { default as File, FileOptions } from '../../../File.ts';
7
8
  export type { default as Reference, ReferenceOptions } from '../../../Reference.ts';
@@ -25,4 +26,6 @@ declare class Overlay1DereferenceStrategy extends DereferenceStrategy {
25
26
  dereference(file: File, options: ReferenceOptions): Promise<Element>;
26
27
  }
27
28
  export { dereferenceExtends } from './extends.ts';
29
+ export { Overlay1DereferenceVisitor };
30
+ export type { Overlay1DereferenceVisitorOptions } from './visitor.ts';
28
31
  export default Overlay1DereferenceStrategy;
@@ -0,0 +1,21 @@
1
+ import { Element } from '@speclynx/apidom-datamodel';
2
+ import type { Path } from '@speclynx/apidom-traverse';
3
+ import Reference from '../../../Reference.ts';
4
+ import type { ReferenceOptions } from '../../../options/index.ts';
5
+ /**
6
+ * @public
7
+ */
8
+ export interface Overlay1DereferenceVisitorOptions {
9
+ readonly reference: Reference;
10
+ readonly options: ReferenceOptions;
11
+ }
12
+ /**
13
+ * @public
14
+ */
15
+ declare class Overlay1DereferenceVisitor {
16
+ protected readonly reference: Reference;
17
+ protected readonly options: ReferenceOptions;
18
+ constructor({ reference, options }: Overlay1DereferenceVisitorOptions);
19
+ ReusableActionReferenceElement(path: Path<Element>): void;
20
+ }
21
+ export default Overlay1DereferenceVisitor;