@speclynx/apidom-reference 5.2.6 → 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.6",
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,36 +299,35 @@
299
299
  "license": "Apache-2.0",
300
300
  "dependencies": {
301
301
  "@babel/runtime-corejs3": "^8.0.5",
302
- "@speclynx/apidom-core": "5.2.6",
303
- "@speclynx/apidom-datamodel": "5.2.6",
304
- "@speclynx/apidom-error": "5.2.6",
305
- "@speclynx/apidom-json-pointer": "5.2.6",
306
- "@speclynx/apidom-ns-arazzo-1": "5.2.6",
307
- "@speclynx/apidom-ns-asyncapi-2": "5.2.6",
308
- "@speclynx/apidom-ns-json-schema-2020-12": "5.2.6",
309
- "@speclynx/apidom-ns-openapi-2": "5.2.6",
310
- "@speclynx/apidom-ns-openapi-3-0": "5.2.6",
311
- "@speclynx/apidom-ns-openapi-3-1": "5.2.6",
312
- "@speclynx/apidom-ns-overlay-1": "5.2.6",
313
- "@speclynx/apidom-parser-adapter-arazzo-json-1": "5.2.6",
314
- "@speclynx/apidom-parser-adapter-arazzo-yaml-1": "5.2.6",
315
- "@speclynx/apidom-parser-adapter-asyncapi-json-2": "5.2.6",
316
- "@speclynx/apidom-parser-adapter-asyncapi-yaml-2": "5.2.6",
317
- "@speclynx/apidom-parser-adapter-json": "5.2.6",
318
- "@speclynx/apidom-parser-adapter-openapi-json-2": "5.2.6",
319
- "@speclynx/apidom-parser-adapter-openapi-json-3-0": "5.2.6",
320
- "@speclynx/apidom-parser-adapter-openapi-json-3-1": "5.2.6",
321
- "@speclynx/apidom-parser-adapter-openapi-yaml-2": "5.2.6",
322
- "@speclynx/apidom-parser-adapter-openapi-yaml-3-0": "5.2.6",
323
- "@speclynx/apidom-parser-adapter-openapi-yaml-3-1": "5.2.6",
324
- "@speclynx/apidom-parser-adapter-overlay-json-1": "5.2.6",
325
- "@speclynx/apidom-parser-adapter-overlay-yaml-1": "5.2.6",
326
- "@speclynx/apidom-parser-adapter-yaml-1-2": "5.2.6",
327
- "@speclynx/apidom-traverse": "5.2.6",
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",
331
- "process": "^0.11.10",
332
331
  "ramda": "~0.32.0",
333
332
  "ramda-adjunct": "^6.1.0"
334
333
  },
@@ -346,5 +345,5 @@
346
345
  "README.md",
347
346
  "CHANGELOG.md"
348
347
  ],
349
- "gitHead": "c78f4a79e2b91b9ad099dff6dff5dc35236ae75b"
348
+ "gitHead": "d2ea4f01cac54a0d5e1030386e3b0b60664c9619"
350
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
@@ -1,11 +1,9 @@
1
1
  "use strict";
2
2
 
3
- var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
4
3
  Object.defineProperty(exports, "__esModule", {
5
4
  value: true
6
5
  });
7
6
  exports.unsanitize = exports.toFileSystemPath = exports.stripHash = exports.sanitize = exports.resolve = exports.relative = exports.isURI = exports.isHttpUrl = exports.isFileSystemPath = exports.hasProtocol = exports.getProtocol = exports.getHash = exports.getExtension = exports.getBasename = exports.fromFileSystemPath = exports.cwd = void 0;
8
- var _process = _interopRequireDefault(require("process"));
9
7
  var _ramda = require("ramda");
10
8
  var _ramdaAdjunct = require("ramda-adjunct");
11
9
  /**
@@ -18,7 +16,7 @@ var _ramdaAdjunct = require("ramda-adjunct");
18
16
  * @public
19
17
  */
20
18
 
21
- const isWindows = () => (0, _ramda.pathSatisfies)((0, _ramda.test)(/^win/), ['platform'], _process.default);
19
+ const isWindows = () => (0, _ramda.pathSatisfies)((0, _ramda.test)(/^win/), ['platform'], globalThis.process);
22
20
 
23
21
  /**
24
22
  * Returns the protocol of the given URL, or `undefined` if it has no protocol.
@@ -244,11 +242,15 @@ const stripHash = uri => {
244
242
  */
245
243
  exports.stripHash = stripHash;
246
244
  const cwd = () => {
245
+ const {
246
+ process
247
+ } = globalThis;
248
+
247
249
  // @ts-ignore
248
- if (_process.default.browser) {
250
+ if (typeof process?.cwd !== 'function' || process.browser) {
249
251
  return stripHash(globalThis.location.href);
250
252
  }
251
- const path = _process.default.cwd();
253
+ const path = process.cwd();
252
254
  const lastChar = (0, _ramda.last)(path);
253
255
  if (['/', '\\'].includes(lastChar)) {
254
256
  return path;
@@ -264,13 +266,14 @@ exports.cwd = cwd;
264
266
  const resolve = (from, to) => {
265
267
  const resolvedUrl = new URL(to, new URL(from, 'resolve://'));
266
268
  if (resolvedUrl.protocol === 'resolve:') {
267
- // `from` is a relative URL.
269
+ // `from` is a relative URL; a network-path reference (`//host/path`) keeps its authority
268
270
  const {
271
+ host,
269
272
  pathname,
270
273
  search,
271
274
  hash
272
275
  } = resolvedUrl;
273
- return pathname + search + hash;
276
+ return (host ? `//${host}` : '') + pathname + search + hash;
274
277
  }
275
278
  return resolvedUrl.toString();
276
279
  };
package/src/util/url.mjs CHANGED
@@ -1,4 +1,3 @@
1
- import process from 'process';
2
1
  import { pathSatisfies, propOr, pipe, test, last } from 'ramda';
3
2
  import { isUndefined, replaceAll, isNotUndefined, trimCharsEnd } from 'ramda-adjunct';
4
3
 
@@ -12,7 +11,7 @@ import { isUndefined, replaceAll, isNotUndefined, trimCharsEnd } from 'ramda-adj
12
11
  * @public
13
12
  */
14
13
 
15
- const isWindows = () => pathSatisfies(test(/^win/), ['platform'], process);
14
+ const isWindows = () => pathSatisfies(test(/^win/), ['platform'], globalThis.process);
16
15
 
17
16
  /**
18
17
  * Returns the protocol of the given URL, or `undefined` if it has no protocol.
@@ -229,8 +228,12 @@ export const stripHash = uri => {
229
228
  * @public
230
229
  */
231
230
  export const cwd = () => {
231
+ const {
232
+ process
233
+ } = globalThis;
234
+
232
235
  // @ts-ignore
233
- if (process.browser) {
236
+ if (typeof process?.cwd !== 'function' || process.browser) {
234
237
  return stripHash(globalThis.location.href);
235
238
  }
236
239
  const path = process.cwd();
@@ -248,13 +251,14 @@ export const cwd = () => {
248
251
  export const resolve = (from, to) => {
249
252
  const resolvedUrl = new URL(to, new URL(from, 'resolve://'));
250
253
  if (resolvedUrl.protocol === 'resolve:') {
251
- // `from` is a relative URL.
254
+ // `from` is a relative URL; a network-path reference (`//host/path`) keeps its authority
252
255
  const {
256
+ host,
253
257
  pathname,
254
258
  search,
255
259
  hash
256
260
  } = resolvedUrl;
257
- return pathname + search + hash;
261
+ return (host ? `//${host}` : '') + pathname + search + hash;
258
262
  }
259
263
  return resolvedUrl.toString();
260
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;