--- /dev/null
+Creative Commons Legal Code
+
+CC0 1.0 Universal
+
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
+ HEREUNDER.
+
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer
+exclusive Copyright and Related Rights (defined below) upon the creator
+and subsequent owner(s) (each and all, an "owner") of an original work of
+authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for
+the purpose of contributing to a commons of creative, cultural and
+scientific works ("Commons") that the public can reliably and without fear
+of later claims of infringement build upon, modify, incorporate in other
+works, reuse and redistribute as freely as possible in any form whatsoever
+and for any purposes, including without limitation commercial purposes.
+These owners may contribute to the Commons to promote the ideal of a free
+culture and the further production of creative, cultural and scientific
+works, or to gain reputation or greater distribution for their Work in
+part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any
+expectation of additional consideration or compensation, the person
+associating CC0 with a Work (the "Affirmer"), to the extent that he or she
+is an owner of Copyright and Related Rights in the Work, voluntarily
+elects to apply CC0 to the Work and publicly distribute the Work under its
+terms, with knowledge of his or her Copyright and Related Rights in the
+Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be
+protected by copyright and related or neighboring rights ("Copyright and
+Related Rights"). Copyright and Related Rights include, but are not
+limited to, the following:
+
+ i. the right to reproduce, adapt, distribute, perform, display,
+ communicate, and translate a Work;
+ ii. moral rights retained by the original author(s) and/or performer(s);
+iii. publicity and privacy rights pertaining to a person's image or
+ likeness depicted in a Work;
+ iv. rights protecting against unfair competition in regards to a Work,
+ subject to the limitations in paragraph 4(a), below;
+ v. rights protecting the extraction, dissemination, use and reuse of data
+ in a Work;
+ vi. database rights (such as those arising under Directive 96/9/EC of the
+ European Parliament and of the Council of 11 March 1996 on the legal
+ protection of databases, and under any national implementation
+ thereof, including any amended or successor version of such
+ directive); and
+vii. other similar, equivalent or corresponding rights throughout the
+ world based on applicable law or treaty, and any national
+ implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention
+of, applicable law, Affirmer hereby overtly, fully, permanently,
+irrevocably and unconditionally waives, abandons, and surrenders all of
+Affirmer's Copyright and Related Rights and associated claims and causes
+of action, whether now known or unknown (including existing as well as
+future claims and causes of action), in the Work (i) in all territories
+worldwide, (ii) for the maximum duration provided by applicable law or
+treaty (including future time extensions), (iii) in any current or future
+medium and for any number of copies, and (iv) for any purpose whatsoever,
+including without limitation commercial, advertising or promotional
+purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
+member of the public at large and to the detriment of Affirmer's heirs and
+successors, fully intending that such Waiver shall not be subject to
+revocation, rescission, cancellation, termination, or any other legal or
+equitable action to disrupt the quiet enjoyment of the Work by the public
+as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason
+be judged legally invalid or ineffective under applicable law, then the
+Waiver shall be preserved to the maximum extent permitted taking into
+account Affirmer's express Statement of Purpose. In addition, to the
+extent the Waiver is so judged Affirmer hereby grants to each affected
+person a royalty-free, non transferable, non sublicensable, non exclusive,
+irrevocable and unconditional license to exercise Affirmer's Copyright and
+Related Rights in the Work (i) in all territories worldwide, (ii) for the
+maximum duration provided by applicable law or treaty (including future
+time extensions), (iii) in any current or future medium and for any number
+of copies, and (iv) for any purpose whatsoever, including without
+limitation commercial, advertising or promotional purposes (the
+"License"). The License shall be deemed effective as of the date CC0 was
+applied by Affirmer to the Work. Should any part of the License for any
+reason be judged legally invalid or ineffective under applicable law, such
+partial invalidity or ineffectiveness shall not invalidate the remainder
+of the License, and in such case Affirmer hereby affirms that he or she
+will not (i) exercise any of his or her remaining Copyright and Related
+Rights in the Work or (ii) assert any associated claims and causes of
+action with respect to the Work, in either case contrary to Affirmer's
+express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
+ surrendered, licensed or otherwise affected by this document.
+ b. Affirmer offers the Work as-is and makes no representations or
+ warranties of any kind concerning the Work, express, implied,
+ statutory or otherwise, including without limitation warranties of
+ title, merchantability, fitness for a particular purpose, non
+ infringement, or the absence of latent or other defects, accuracy, or
+ the present or absence of errors, whether or not discoverable, all to
+ the greatest extent permissible under applicable law.
+ c. Affirmer disclaims responsibility for clearing rights of other persons
+ that may apply to the Work or any use thereof, including without
+ limitation any person's Copyright and Related Rights in the Work.
+ Further, Affirmer disclaims responsibility for obtaining any necessary
+ consents, permissions or other rights required for any use of the
+ Work.
+ d. Affirmer understands and acknowledges that Creative Commons is not a
+ party to this document and has no duty or obligation with respect to
+ this CC0 or use of the Work.
-// 📧🏷️ Étiquette ∷ model.js
-// ====================================================================
-//
-// Copyright © 2023 Lady [@ Lady’s Computer].
-//
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
+// SPDX-FileCopyrightText: 2023, 2025 Lady <https://www.ladys.computer/about/#lady>
+// SPDX-License-Identifier: MPL-2.0
+/**
+ * ⁌ 📧🏷️ Étiquette ∷ model.js
+ *
+ * Copyright © 2023, 2025 Lady [@ Ladys Computer].
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
+ */
import { identity } from "./deps.js";
import { Storage } from "./memory.js";
import { taggingDiscoveryContext } from "./names.js";
import schema from "./schema.js";
+const ÉTIQUETTE = "📧🏷️ Étiquette";
+
/**
* A tag.
*
- * `Tag`s are not assigned identifiers and do not have side·effects on
- * other tags in the `TagSystem` until they are persisted with
- * `::persist`, at which point changes to their relationships are
+ * `Tag´s are not assigned identifiers and do not have side·effects on
+ * other tags in the `TagSystem´ until they are persisted with
+ * `::persist´, at which point changes to their relationships are
* applied.
*
- * `Tag`s are also not kept up‐to‐date, but persisting an outdated
- * `Tag` will *not* undo subsequent changes.
+ * `Tag´s are also not kept up‐to‐date, but persisting an outdated
+ * `Tag´ will ⹐not⹑ undo subsequent changes.
*
* ※ This class is not itself directly exposed, although bound
- * versions of it are via `TagSystem::Tag`.
+ * versions of it are via `TagSystem::Tag´.
*/
class Tag {
- /** The `TagSystem` this `Tag` belongs to. */
+ /** The `TagSystem´ this `Tag´ belongs to. */
#system;
- /** The `Storage` managed by this `Tag`’s `TagSystem`. */
+ /** The `Storage´ managed by this `Tag´s `TagSystem´. */
#storage;
- /** The schema in use for this `Tag`. */
+ /** The schema in use for this `Tag´. */
#schema;
/**
* The 30‐bit W·R·M·G base32 identifier with leading checksum which
- * has been assigned to this `Tag`.
+ * has been assigned to this `Tag´.
*
- * Will be `null` if this `Tag` has not been persisted. Otherwise,
- * the format is `cxx-xxxx` (`c` = checksum; `x` = digit).
+ * Will be `null´ if this `Tag´ has not been persisted. Otherwise,
+ * the format is `cxx-xxxx´ (`c´ = checksum; `x´ = digit).
*/
#identifier = null;
- /** The kind of this `Tag`. */
+ /** The kind of this `Tag´. */
#kind = "Tag";
/**
- * The data which was attached to this `Tag` the last time it was
+ * The data which was attached to this `Tag´ the last time it was
* persisted or retrieved from storage.
*
* Diffing with this will reveal changes.
*/
#persistedData = null;
- /** The current (modified) data associated with this `Tag`. */
+ /** The current (modified) data associated with this `Tag´. */
#data = tagData();
/**
- * Adds the provided label(s) to this `Tag` as the provided
- * predicate, then returns this `Tag`.
+ * Adds the provided label(s) to this `Tag´ as the provided
+ * predicate, then returns this `Tag´.
*/
#addLabel(predicate, ...labels) {
const values = this.#data[predicate];
}
/**
- * Adds the provided tags to the list of tags that this `Tag` is
- * related to by the provided predicate, then returns this `Tag`.
+ * Adds the provided tags to the list of tags that this `Tag´ is
+ * related to by the provided predicate, then returns this `Tag´.
*
* Arguments may be string identifiers or objects with an
- * `.identifier` property.
+ * `.identifier´ property.
*/
#addTag(predicate, ...tags) {
const storage = this.#storage;
if (identifier == null) {
// ☡ The current tag has no identifier.
throw new TypeError(
- `Cannot state ${predicate} of Tag: Identifier must not be nullish.`,
+ `${ÉTIQUETTE}: Cannot state ${predicate} of Tag: Identifier must not be nullish.`,
);
} else if (values.has(identifier)) {
// Short‐circuit: The identifier has already been stated with
// this predicate.
/* do nothing */
} else {
- // The current tag has an identifier, but it hasn’t been stated
+ // The current tag has an identifier, but it hasn¦t been stated
// with this predicate yet.
const tag = storage.get(identifier);
if (tag == null) {
- // ☡ The current tag has not been persisted to this `Tag`’s
+ // ☡ The current tag has not been persisted to this `Tag´s
// storage.
throw new RangeError(
- `Cannot state ${predicate} of Tag: Identifier is not persisted: ${identifier}.`,
+ `${ÉTIQUETTE}: Cannot state ${predicate} of Tag: Identifier is not persisted: ${identifier}.`,
);
} else if (!this.#isTagInStorage(tag)) {
// ☡ The current tag is not a tag in the correct tag system.
throw new TypeError(
- `Cannot state ${predicate} of Tag: Tags must be from the same Tag System, but got: ${identifier}.`,
+ `${ÉTIQUETTE}: Cannot state ${predicate} of Tag: Tags must be from the same Tag System, but got: ${identifier}.`,
);
} else if (
!isObjectPredicateOK(
// ☡ This tag and the current tag form an invalid pair for
// this predicate.
throw new TypeError(
- `Cannot state ${predicate} of Tag: Not valid for domain and range: ${this.#kind}, ${tag.#kind}.`,
+ `${ÉTIQUETTE}: Cannot state ${predicate} of Tag: Not valid for domain and range: ${this.#kind}, ${tag.#kind}.`,
);
} else {
// The current tag is a tag in the correct tag system; add
}
/**
- * Removes the provided string label(s) from this `Tag` as the
- * provided predicate, then returns this `Tag`.
+ * Removes the provided string label(s) from this `Tag´ as the
+ * provided predicate, then returns this `Tag´.
*/
#deleteLabel(predicate, ...labels) {
const values = this.#data[predicate];
}
/**
- * Removes the provided tags from the list of tags that this `Tag` is
- * related to by the provided predicate, then returns this `Tag`.
+ * Removes the provided tags from the list of tags that this `Tag´ is
+ * related to by the provided predicate, then returns this `Tag´.
*
* Arguments may be string identifiers or objects with an
- * `.identifier` property.
+ * `.identifier´ property.
*/
#deleteTag(predicate, ...tags) {
const values = this.#data[predicate];
* Returns whether or not the provided value is a tag which shares a
* storage with this tag.
*
- * Sharing a storage also implies sharing a `TagSystem`.
+ * Sharing a storage also implies sharing a `TagSystem´.
*/
#isTagInStorage($) {
try {
- // Try to compare the provided value’s internal store with
+ // Try to compare the provided values internal store with
// the provided storage.
return $.#storage == this.#storage;
} catch {
}
/**
- * Yields the labels of this `Tag` according to the provided
+ * Yields the labels of this `Tag´ according to the provided
* predicate.
*/
*#yieldLabels(predicate) {
}
/**
- * Yields the tags that this `Tag` is related to by the provided
+ * Yields the tags that this `Tag´ is related to by the provided
* predicate.
*/
*#yieldTags(predicate) {
}
/**
- * Yields the tags that this `Tag` is related to by the provided
+ * Yields the tags that this `Tag´ is related to by the provided
* predicate, figured transitively.
*/
*#yieldTransitiveTags(transitivePredicate, basePredicate) {
}
/**
- * Constructs a new `Tag` of the provided kind and with the provided
+ * Constructs a new `Tag´ of the provided kind and with the provided
* preferred label.
*
* ※ The first two arguments of this constructor are bound when
- * generating the value of `TagSystem::Tag`. It isn’t possible to
+ * generating the value of `TagSystem::Tag´. It isn¦t possible to
* access this constructor in its unbound form from outside this
* module.
*
if (!(kindString in schema.classes)) {
// The provided kind is not supported.
throw new RangeError(
- `Cannot construct Tag: Unrecognized kind: ${kind}.`,
+ `${ÉTIQUETTE}: Cannot construct Tag: Unrecognized kind: ${kind}.`,
);
} else {
// The provided kind is one of the recognized tag kinds.
}
/**
- * Returns a new `Tag` constructor for the provided system, storage,
+ * Returns a new `Tag´ constructor for the provided system, storage,
* schema, created with an appropriate prototype for the properties
* so defined.
*
// The current key does not indicate an inverse
// property, so add and delete methods are also
// added.
- const cased = key[0].toUpperCase() +
- key.substring(1);
+ const cased = key[0].toUpperCase()
+ + key.substring(1);
yield [`add${cased}Tag`, function (...tags) {
return this.#addTag(key, ...tags);
}];
/* do nothing */
}
if (
- subPropertyOf != null &&
- subPropertyOf in transitiveProperties
+ subPropertyOf != null
+ && subPropertyOf in transitiveProperties
) {
// The current key indicates a subproperty of a
// transitive property; its method is also added.
// Iterate over each data property and yield any
// necessary method definitions.
if (key != "prefLabel") {
- // The current key is not `"prefLabel"`.
- const cased = key[0].toUpperCase() +
- key.substring(1);
+ // The current key is not `"prefLabel"´.
+ const cased = key[0].toUpperCase()
+ + key.substring(1);
yield [`${key}s`, function* () {
yield* this.#yieldLabels(key);
}];
return this.#deleteLabel(key, ...labels);
}];
} else {
- // The current key is `"prefLabel"`. This is a
+ // The current key is `"prefLabel"´. This is a
// special case which is not handled by the schema.
/* do nothing */
}
/**
* Assigns the provided data and identifier to the provided tag.
*
- * ☡ This function throws if the provided tag is not a `Tag`.
+ * ☡ This function throws if the provided tag is not a `Tag´.
*
* ※ This function is not exposed.
*/
}
/**
- * Returns a new `Tag` with the provided identifier, kind, and
+ * Returns a new `Tag´ with the provided identifier, kind, and
* prefLabel.
*
- * ※ This function exists to enable `TagSystem`s to replay Create
+ * ※ This function exists to enable `TagSystem´s to replay Create
* activities, maintaining the identifier of the original.
*
* ☡ This function throws if the provided identifier is already in
const storage = (new system.Tag()).#storage;
if (storage.has(identifier)) {
throw new RangeError(
- `Cannot create Tag: Identifier already in use: ${identifier}.`,
+ `${ÉTIQUETTE}: Cannot create Tag: Identifier already in use: ${identifier}.`,
);
} else {
const createdTag = new system.Tag(kind, prefLabel);
}
/**
- * Returns the `TagSystem` that the provided value belongs to.
+ * Returns the `TagSystem´ that the provided value belongs to.
*
* ※ This function can be used to check if the provided value has
* private tag features.
*
- * ※ `Tag::system` is an overridable, publicly‐accessible means of
+ * ※ `Tag::system´ is an overridable, publicly‐accessible means of
* accessing the system.
*
* ※ This function is not exposed.
}
static {
- // Overwrite the default `::constructor` method to instead give the
+ // Overwrite the default `::constructor´ method to instead give the
// actual (bound) constructor which was used to generate a given
- // `Tag`.
+ // `Tag´.
Object.defineProperties(this.prototype, {
constructor: {
configurable: true,
enumerable: false,
get() {
- // All `Tag`s are constructed via the `.Tag` constructor
- // available in their `TagSystem`; return it.
+ // All `Tag´s are constructed via the `.Tag´ constructor
+ // available in their `TagSystem´; return it.
return this.#system.Tag;
},
set: undefined,
});
}
- /** Returns the authority (domain) name for this `Tag`. */
+ /** Returns the authority (domain) name for this `Tag´. */
get authorityName() {
return this.#system.authorityName;
}
- /** Returns the identifier of this `Tag`. */
+ /** Returns the identifier of this `Tag´. */
get identifier() {
return this.#identifier;
}
- /** Returns the I·R·I for this `Tag`. */
+ /** Returns the I·R·I for this `Tag´. */
get iri() {
const { identifier, iriSpace } = this;
return identifier == null ? null : `${iriSpace}${identifier}`;
}
- /** Returns the I·R·I space for this `Tag`. */
+ /** Returns the I·R·I space for this `Tag´. */
get iriSpace() {
return this.#system.iriSpace;
}
- /** Returns the kind of this `Tag`. */
+ /** Returns the kind of this `Tag´. */
get kind() {
return this.#kind;
}
/**
- * Returns the `TagSystem` for this `Tag`.
+ * Returns the `TagSystem´ for this `Tag´.
*
- * ※ Internally, `Tag.getSystem` is preferred.
+ * ※ Internally, `Tag.getSystem´ is preferred.
*/
get system() {
return this.#system;
}
/**
- * Persist this `Tag` to storage and return an ActivityStreams
+ * Persist this `Tag´ to storage and return an ActivityStreams
* serialization of a Tag Activity representing any changes, or
- * `null` if no changes were made.
+ * `null´ if no changes were made.
*
- * If the second argument is `true`, the `Tag` will be persisted but
+ * If the second argument is `true´, the `Tag´ will be persisted but
* no serialization will be made. This is somewhat more efficient.
*
* ※ Persistence can imply side‐effects on other objects, which are
// Iterate over each entry of the tag data and create a diff
// with the last persisted information.
if (
- objectProperties[key]?.inverseOf != null ||
- silent && key in dataProperties
+ objectProperties[key]?.inverseOf != null
+ || silent && key in dataProperties
) {
// The current property is one which is skipped in diffs.
//
}
diffs[key] = { old: oldValues, new: newValues };
} else if (
- `${value}` != `${persisted}` ||
- value.language != persisted.language
+ `${value}` != `${persisted}`
+ || value.language != persisted.language
) {
// The current property is (optionally language‐tagged)
// string‐valued and the value changed.
}
const identifier = this.#identifier;
if (identifier != null) {
- // This `Tag` has already been persisted; use its existing
+ // This `Tag´ has already been persisted; use its existing
// identifier and persist.
storage.set(identifier, this);
} else {
- // This `Tag` has not been persisted yet; save the new
+ // This `Tag´ has not been persisted yet; save the new
// identifier after persisting.
this.#identifier = storage.add(this);
}
// The current property is the inverse of a non‐transitive
// property.
for (const referencedIdentifier of diffs[term].old) {
- // Iterate over the removed tags and remove this `Tag` from
+ // Iterate over the removed tags and remove this `Tag´ from
// their inverse property.
const referenced = storage.get(referencedIdentifier);
try {
- // Try removing this `Tag`.
+ // Try removing this `Tag´.
referenced.#data[inverse].delete(persistedIdentifier);
storage.set(referencedIdentifier, referenced);
} catch {
referenced.#data[inverse].add(persistedIdentifier);
storage.set(referencedIdentifier, referenced);
} catch {
- // Adding failed, possibly because the other tag was deleted.
+ // Adding failed, possibly because the other tag was
+ // deleted.
/* do nothing */
}
}
});
}
} catch {
- // Value resolution failed for some reason; perhaps the
- // tag was deleted.
+ // Value resolution failed for some reason; perhaps
+ // the tag was deleted.
/* do nothing */
}
}
});
}
} catch {
- // Value resolution failed for some reason; perhaps the
- // tag was deleted.
+ // Value resolution failed for some reason; perhaps
+ // the tag was deleted.
/* do nothing */
}
}
})(),
};
if (
- !Object.hasOwn(activity, "states") &&
- !Object.hasOwn(activity, "unstates")
+ !Object.hasOwn(activity, "states")
+ && !Object.hasOwn(activity, "unstates")
) {
// No meaningful changes were actually persisted.
return null;
} else {
- // There were meaningful changes persisted regarding this `Tag`.
+ // There were meaningful changes persisted regarding this
+ // `Tag´.
return activity;
}
}
}
- /** Returns the preferred label for this `Tag`. */
+ /** Returns the preferred label for this `Tag´. */
get prefLabel() {
return this.#data.prefLabel;
}
- /** Sets the preferred label of this `Tag` to the provided label. */
+ /** Sets the preferred label of this `Tag´ to the provided label. */
set prefLabel($) {
this.#data.prefLabel = langString($);
}
- /** Returns the Tag U·R·I for this `Tag`. */
+ /** Returns the Tag U·R·I for this `Tag´. */
get tagURI() {
const { identifier } = this;
return identifier == null
: `tag:${this.taggingEntity}:${identifier}`;
}
- /** Returns the tagging entity (domain and date) for this `Tag`. */
+ /** Returns the tagging entity (domain and date) for this `Tag´. */
get taggingEntity() {
return this.#system.taggingEntity;
}
- /** Returns the string form of the preferred label of this `Tag`. */
+ /** Returns the string form of the preferred label of this `Tag´. */
toString() {
return `${this.#data.prefLabel}`;
}
const {
/**
- * A `Tag` constructor function.
+ * A `Tag´ constructor function.
*
* This class extends the identity function, meaning that the object
* provided as the constructor is used verbatim (with new private
* fields added).
*
* ※ The instance methods of this class are provided as static
- * methods on the superclass which all `Tag` constructors inherit
+ * methods on the superclass which all `Tag´ constructors inherit
* from.
*
* ※ This class is not exposed.
TagConstructor,
/**
- * The exposed constructor function from which all `Tag` constructors
+ * The exposed constructor function from which all `Tag´ constructors
* inherit.
*
* ☡ This constructor always throws.
return {
TagConstructor: class extends identity {
/**
- * The `TagSystem` used for `Tag`s constructed by this
+ * The `TagSystem´ used for `Tag´s constructed by this
* constructor.
*/
#system;
- /** The `Storage` managed by this constructor’s `TagSystem`. */
+ /** The `Storage´ managed by this constructors `TagSystem´. */
#storage;
/** The schema in use for this constructor. */
#schema;
/**
- * Constructs a new `Tag` constructor by adding the appropriate
+ * Constructs a new `Tag´ constructor by adding the appropriate
* private fields to the provided constructor, setting its
* prototype, and then returning it.
*
- * ※ This constructor does not modify the `name` or `prototype`
+ * ※ This constructor does not modify the `name´ or `prototype´
* properties of the provided constructor.
*
- * ※ See `Tag.For`, where this constructor is used.
+ * ※ See `Tag.For´, where this constructor is used.
*/
constructor(constructor, system, storage, schema) {
super(constructor);
}
static {
- // Define the superclass constructor which all `Tag`
+ // Define the superclass constructor which all `Tag´
// constructors will inherit from.
const superclass = tagConstructorBehaviours.TagSuper =
function Tag() {
}
/**
- * Yields the tags in the `TagSystem` associated with this
+ * Yields the tags in the `TagSystem´ associated with this
* constructor.
*/
*all() {
const storage = this.#storage;
for (const instance of storage.values()) {
// Iterate over the entries and yield the ones which are
- // `Tag`s in this `TagSystem`.
+ // `Tag´s in this `TagSystem´.
if (Tag.getSystem(instance) == system) {
- // The current instance is a `Tag` in this `TagSystem`.
+ // The current instance is a `Tag´ in this `TagSystem´.
yield instance;
} else {
- // The current instance is not a `Tag` in this
- // `TagSystem`.
+ // The current instance is not a `Tag´ in this
+ // `TagSystem´.
/* do nothing */
}
}
}
/**
- * Returns a new `Tag` resolved from the provided I·R·I.
+ * Returns a new `Tag´ resolved from the provided I·R·I.
*
- * ☡ This function throws if the I·R·I is not in the `.iriSpace`
- * of the `TagSystem` associated with this constructor.
+ * ☡ This function throws if the I·R·I is not in the `.iriSpace´
+ * of the `TagSystem´ associated with this constructor.
*
* ※ If the I·R·I is not recognized, this function returns
* `undefined`.
if (!name.startsWith(prefix)) {
// The I·R·I does not begin with the expected prefix.
throw new RangeError(
- `I·R·I did not begin with the expected prefix: ${iri}`,
+ `${ÉTIQUETTE}: I·R·I did not begin with the expected prefix: ${iri}`,
);
} else {
// The I·R·I begins with the expected prefix.
}
/**
- * Returns a new `Tag` resolved from the provided identifier.
+ * Returns a new `Tag´ resolved from the provided identifier.
*
* ☡ This function throws if the identifier is invalid.
*
* ※ If the identifier is valid but not recognized, this
- * function returns `undefined`.
+ * function returns `undefined´.
*/
fromIdentifier(identifier) {
const system = this.#system;
}
/**
- * Returns a new `Tag` resolved from the provided Tag U·R·I.
+ * Returns a new `Tag´ resolved from the provided Tag U·R·I.
*
* ☡ This function throws if the provided Tag U·R·I does not
- * match the tagging entity of this constructor’s `TagSystem`.
+ * match the tagging entity of this constructors `TagSystem´.
*
* ※ If the specific component of the Tag U·R·I is not
- * recognized, this function returns `undefined`.
+ * recognized, this function returns `undefined´.
*/
fromTagURI(tagURI) {
const system = this.#system;
if (!tagName.startsWith(tagPrefix)) {
// The Tag U·R·I does not begin with the expected prefix.
throw new RangeError(
- `Tag U·R·I did not begin with the expected prefix: ${tagURI}`,
+ `${ÉTIQUETTE}: Tag U·R·I did not begin with the expected prefix: ${tagURI}`,
);
} else {
// The I·R·I begins with the expected prefix.
}
/**
- * Yields the tag identifiers in the `TagSystem` associated with
+ * Yields the tag identifiers in the `TagSystem´ associated with
* this constructor.
*/
*identifiers() {
const storage = this.#storage;
for (const [identifier, instance] of storage.entries()) {
// Iterate over the entries and yield the ones which are
- // `Tag`s in this `TagSystem`.
+ // `Tag´s in this `TagSystem´.
if (Tag.getSystem(instance) == system) {
- // The current instance is a `Tag` in this `TagSystem`.
+ // The current instance is a `Tag´ in this `TagSystem´.
yield identifier;
} else {
- // The current instance is not a `Tag` in this `TagSystem`.
+ // The current instance is not a `Tag´ in this `TagSystem´.
/* do nothing */
}
}
}
- /** Returns the `TagSystem` for this `Tag` constructor. */
+ /** Returns the `TagSystem´ for this `Tag´ constructor. */
get system() {
return this.#system;
}
/**
- * Returns a new `Tag` constructed from the provided data and
+ * Returns a new `Tag´ constructed from the provided data and
* with the provided identifier.
*
* ※ This function is not really intended for public usage.
domainUnion.some((domain) =>
domain == "Thing" || domains.has(domain)
)
- ) &&
- rangeIntersection.every((rangeUnion) =>
+ )
+ && rangeIntersection.every((rangeUnion) =>
rangeUnion.some((range) =>
range == "Thing" || ranges.has(range)
)
const {
/**
- * Returns the provided value converted into a `String` object with
- * `.["@value"]` and `.["@language"]` properties.
+ * Returns the provided value converted into a `String´ object with
+ * `.["@value"]´ and `.["@language"]´ properties.
*
* The same object will be returned for every call with an equivalent
* value.
}
};
- /** Returns the `.["@language"]` of this object. */
+ /** Returns the `.["@language"]´ of this object. */
const getLanguage = Object.defineProperty(
function () {
return this["@language"] || null;
);
/**
- * A `FinalizationRegistry` for language string objects.
+ * A `FinalizationRegistry´ for language string objects.
*
- * This simply cleans up the corresponding `WeakRef` in the language
+ * This simply cleans up the corresponding `WeakRef´ in the language
* map.
*/
const langStringRegistry = new FinalizationRegistry(
*/
const languageMap = Object.create(null);
- /** Returns the `.["@value"]` of this object. */
+ /** Returns the `.["@value"]´ of this object. */
const toString = function () {
return this["@value"];
};
/**
- * Returns this object if it has a `.["@language"]`; otherwise, its
- * `.["@value"]`.
+ * Returns this object if it has a `.["@language"]´; otherwise, its
+ * `.["@value"]´.
*/
const valueOf = function () {
return this["@language"] ? this : this["@value"];
/**
* Returns an identifier corresponding to the provided object.
*
- * This is either the value of its `.identifier` or its string value.
+ * This is either the value of its `.identifier´ or its string value.
*
* ※ This function is not exposed.
*/
/**
* A tag system, with storage.
*
- * The `::Tag` constructor available on any `TagSystem` instance can be
- * used to create new `Tag`s within the system.
+ * The `::Tag´ constructor available on any `TagSystem´ instance can be
+ * used to create new `Tag´s within the system.
*/
export class TagSystem {
- /** The cached bound `Tag` constructor for this `TagSystem`. */
+ /** The cached bound `Tag´ constructor for this `TagSystem´. */
#Tag = null;
- /** The domain of this `TagSystem`. */
+ /** The domain of this `TagSystem´. */
#domain;
- /** The date of this `TagSystem`. */
+ /** The date of this `TagSystem´. */
#date;
- /** The identifier of this `TagSystem`. */
+ /** The identifier of this `TagSystem´. */
#identifier;
- /** The schema used by this `TagSystem. */
+ /** The schema used by this `TagSystem´. */
#schema = schema;
- /** The internal `Storage` of this `TagSystem`. */
+ /** The internal `Storage` of this `TagSystem´. */
#storage = new Storage();
/**
- * Constructs a new `TagSystem` with the provided domain and date.
+ * Constructs a new `TagSystem´ with the provided domain and date.
*
* Only actual, lowercased domain names are allowed for the domain,
* and the date must be “full” (include month and day components).
- * This is for alignment with general best practices for Tag URI’s.
+ * This is for alignment with general best practices for Tag U·R·I¦s.
*
* ☡ This constructor throws if provided with an invalid date.
*/
// ☡ The domain is invalid.
throw new RangeError(`Invalid domain: ${domain}.`);
} else if (
- !/^\d{4}-\d{2}-\d{2}$/u.test(dateString) ||
- dateString != new Date(dateString).toISOString().split("T")[0]
+ !/^\d{4}-\d{2}-\d{2}$/u.test(dateString)
+ || dateString != new Date(dateString).toISOString().split("T")[0]
) {
// ☡ The date is invalid.
throw new RangeError(`Invalid date: ${date}.`);
}
/**
- * Returns a bound constructor for constructing `Tags` in this
- * `TagSystem`.
+ * Returns a bound constructor for constructing `Tags´ in this
+ * `TagSystem´.
*/
get Tag() {
if (this.#Tag != null) {
}
/**
- * Applies the provided activity to this `TagSystem` by replaying its
+ * Applies the provided activity to this `TagSystem´ by replaying its
* statement changes.
*
* ※ This method assumes that the provided activity conforms to the
if (!object) {
// ☡ The provided activity has no object.
throw new TypeError(
- "Cannot apply activity: Activity lacks an object.",
+ `${ÉTIQUETTE}: Cannot apply activity: Activity lacks an object.`,
);
} else {
// The provided activity has an object.
// Extract the identifier from the object I·R·I.
if (!iri.startsWith(iriSpace)) {
// ☡ The object of the provided activity is not in the I·R·I
- // space of this `TagSystem`.
+ // space of this `TagSystem´.
throw new RangeError(
`Cannot apply activity: Object is not in I·R·I space: ${object}`,
);
} else {
// ☡ The object of the provided activity is in the I·R·I
- // space of this `TagSystem`.
+ // space of this `TagSystem´.
return iri.substring(iriSpace.length);
}
})();
if (!tag) {
// ☡ Resolving the tag identifier failed.
throw new RangeError(
- `Cannot apply activity: No tag for identifier: ${identifier}.`,
+ `${ÉTIQUETTE}: Cannot apply activity: No tag for identifier: ${identifier}.`,
);
} else {
// Resolving the identifier succeeded; apply the changes to the
const predicate = `${$p}`;
const term = predicate in dataProperties
? langString($o)
- : predicate in objectProperties &&
- !(predicate in transitiveProperties ||
- objectProperties[predicate].inverseOf != null)
+ : predicate in objectProperties
+ && !(predicate in transitiveProperties
+ || objectProperties[predicate].inverseOf != null)
? `${$o}`
: null;
if (term == null) {
tag.prefLabel = term;
}
} else {
- // The predicate is not `"prefLabel"`.
+ // The predicate is not `"prefLabel"´.
const related = (() => {
// If the predicate is an object property, attempt to
// resolve the object.
}
}
- /** Returns the authority name (domain) for this `TagSystem`. */
+ /** Returns the authority name (domain) for this `TagSystem´. */
get authorityName() {
return this.#domain;
}
- /** Returns the date of this `TagSystem`, as a string. */
+ /** Returns the date of this `TagSystem´, as a string. */
get date() {
return this.#date;
}
/**
- * Yields the entities in this `TagSystem`.
+ * Yields the entities in this `TagSystem´.
*
* ※ Entities can hypothetically be anything. If you specifically
- * want the `Tag`s, use `::Tag.all` instead.
+ * want the `Tag´s, use `::Tag.all´ instead.
*/
*entities() {
yield* this.#storage.values();
}
/**
- * Returns the identifier of this `TagSystem`.
+ * Returns the identifier of this `TagSystem´.
*
* ※ Often this is just the empty string.
*/
return this.#identifier;
}
- /** Yields the identifiers in use in this `TagSystem`. */
+ /** Yields the identifiers in use in this `TagSystem´. */
*identifiers() {
yield* this.#storage.keys();
}
- /** Returns the I·R·I for this `TagSystem`. */
+ /** Returns the I·R·I for this `TagSystem´. */
get iri() {
return `${this.iriSpace}${this.identifier}`;
}
/**
- * Returns the prefix used for I·R·I’s of `Tag`s in this `TagSystem`.
+ * Returns the prefix used for I·R·I¦s of `Tag´s in this `TagSystem´.
*/
get iriSpace() {
return `https://${this.authorityName}/tag:${this.taggingEntity}:`;
}
- /** Returns the Tag U·R·I for this `TagSystem`. */
+ /** Returns the Tag U·R·I for this `TagSystem´. */
get tagURI() {
return `tag:${this.taggingEntity}:${this.identifier}`;
}
/**
- * Returns the tagging entity (domain and date) for this `TagSystem`.
+ * Returns the tagging entity (domain and date) for this `TagSystem´.
*/
get taggingEntity() {
return `${this.authorityName},${this.date}`;