Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | 6x 1x 5x 5x 4x 4x 1x 17x 17x 11x 6x 6x 5x 1x 79x 64x 15x 94x 21x 1x 20x 21x 3x 17x 17x 1x 16x 48x 48x 25x 25x 5x 5x 4x 1x 5x 5x 94x 57x 1x 56x 3x 414x 53x 228x 228x 45x 8x 57x | /**
* Get a transformed version of the URI that can be used as a JSON identifier which only contains letters, numbers and dots.
* @param iri A URI.
* @returns A transformed version which only contains letters, numbers and dots.
*/
export function toJsonId(iri: string): string | undefined {
if (!iri) {
return iri;
}
let u = iri.split('//')[1];
if (u) {
u = u.replace(/[^a-zA-Z0-9]/g, '.');
return u.endsWith('.') ? u.slice(0, -1) : u;
} else {
return undefined;
}
}
/**
* Get the IRI from a node ID in the form of `<http://example.com/resource>`.
* If the node ID does not contain angle brackets, it is returned as is.
* @param id A node ID.
* @returns The IRI corresponding to the node ID.
*/
export function getIriFromNodeId(id: string): string {
const n = id.lastIndexOf('<');
if (n === -1) {
return id;
}
const m = id.lastIndexOf('>');
if (n < m) {
return id.substring(n + 1, m);
} else {
return id;
}
}
/**
* Get the local part and query from an IRI string.
* @param iri An IRI string.
* @returns The local part and query of the IRI, or the IRI itself if it does not contain a local part or query.
*/
export function getLocalPartAndQuery(iri: string): string {
if (iri.includes('#')) {
return iri.split('#').pop() || iri;
} else {
return iri.split('/').pop() || iri;
}
}
/**
* The characters that may precede the local part of an IRI in its written form: the
* colon of a prefixed name or of an XML entity-free qualified name, the namespace
* separators `/` and `#`, the semicolon of an XML entity reference (`&ns;local`) and
* the opening bracket of a relative IRI reference (`<local>`).
*/
const LOCAL_PART_SEPARATORS = new Set([':', '/', '#', ';', '<']);
/**
* Get the offset of the local part of an IRI within the text of one of its written
* occurrences, e.g. `ex:Thing`, `<http://example.org/ns#Thing>`, `http://example.org/ns#Thing`
* or `&ex;Thing`. Only the local part is rewritten when an IRI is renamed, so this works for
* every syntax and prefix an occurrence uses.
* @param referenceText The text of the occurrence, e.g. the text of an indexed reference range.
* @param localPart The local part of the IRI.
* @returns The offset of the local part in the text, or `undefined` if the text does not end
* with the local part as a whole, e.g. because the text is stale or uses escape sequences.
*/
export function getLocalPartOffset(referenceText: string, localPart: string): number | undefined {
if (!localPart) {
return undefined;
}
// The local part of an IRI reference ends before its closing bracket.
const text = referenceText.startsWith('<') && referenceText.endsWith('>')
? referenceText.slice(0, -1)
: referenceText;
if (!text.endsWith(localPart)) {
return undefined;
}
const offset = text.length - localPart.length;
// A relative IRI in an RDF/XML attribute value consists of the local part only.
if (offset === 0) {
return 0;
}
return LOCAL_PART_SEPARATORS.has(text[offset - 1]) ? offset : undefined;
}
/**
* Strip the URI scheme and authority from a URI string and decode percent-encoded characters,
* returning a human-readable path suitable for display.
* @param uri A URI string (e.g. `workspace:///my%20shapes/file.ttl` or a plain path).
* @returns The decoded path without scheme prefix, or the decoded input if it contains no scheme.
*/
export function toDisplayPath(uri: string): string {
const stripped = uri.replace(/^[^:]+:\/\/\//, '');
return decodeURIComponent(stripped);
}
/**
* Get the file name from a URI string.
* @param uri A URI string.
* @returns The file name, or the URI itself if it does not contain a file name.
*/
export function getFileName(uri: string): string {
const parts = toDisplayPath(uri).split('/');
return parts.length > 0 ? parts[parts.length - 1] : uri;
}
/**
* Get the folder path from a URI string.
* @param uri A URI string.
* @returns The folder path, or the URI itself if it does not contain a path.
*/
export function getPath(uri: string): string {
const parts = toDisplayPath(uri).split('/');
if (parts.length > 1) {
return parts.slice(0, -1).join('/');
} else {
return uri;
}
}
/**
* Get the folder part of a URI string, without the trailing file name.
*
* Unlike {@link getPath}, a URI that consists of a file name only yields an empty
* string rather than the input, so callers can distinguish "no folder" from "a folder
* that happens to be named like a file".
* @param uri A URI string.
* @returns The decoded folder path, or an empty string if the URI has no folder part.
*/
export function getFolderPath(uri: string): string {
const parts = toDisplayPath(uri).split('/');
return parts.length > 1 ? parts.slice(0, -1).join('/') : '';
}
/**
* The marker standing in for the path segments omitted by {@link shortenPathStart}.
*/
const PATH_ELLIPSIS = '…';
/**
* Shorten a display path from the start, so that its trailing and most specific segments
* stay readable inside a width-constrained list column.
*
* Leading segments are dropped whole and replaced by an ellipsis. Only when the last
* segment alone still exceeds the budget is it truncated mid-segment.
* @param path A display path, such as the result of {@link toDisplayPath}.
* @param maxLength The maximum number of characters of the returned string.
* @returns The path unchanged if it fits, otherwise an ellipsis-prefixed tail of it.
*/
export function shortenPathStart(path: string, maxLength: number): string {
if (maxLength <= 0) {
return '';
}
if (path.length <= maxLength) {
return path;
}
const segments = path.split('/').filter(segment => segment.length > 0);
for (let index = 1; index < segments.length; index++) {
const tail = `${PATH_ELLIPSIS}/${segments.slice(index).join('/')}`;
if (tail.length <= maxLength) {
return tail;
}
}
const lastSegment = segments[segments.length - 1] ?? path;
return PATH_ELLIPSIS + lastSegment.slice(lastSegment.length - (maxLength - PATH_ELLIPSIS.length));
}
|