From eeeb266fd27de83a7c9869fb368030577c9f5a66 Mon Sep 17 00:00:00 2001 From: Benjamin Wegener Date: Sun, 19 Nov 2023 16:32:20 +0000 Subject: [PATCH] feat(core) basic structure --- lib/core/Cetra.js | 136 ++++++++++++++++++++++++++++++++++++++++++++++ lib/lib.js | 3 + 2 files changed, 139 insertions(+) create mode 100644 lib/core/Cetra.js create mode 100644 lib/lib.js diff --git a/lib/core/Cetra.js b/lib/core/Cetra.js new file mode 100644 index 0000000..2f7e102 --- /dev/null +++ b/lib/core/Cetra.js @@ -0,0 +1,136 @@ +import Emitter from './Emitter'; +import Logger from './Logger'; +class Cetra extends Emitter { + // class static globals + static #instances = new Map(); + static #uidIndex = new Set(); + static #defaultSettings = new Map([ + ['selector', 'ctra'], + ['root', document.body], + #identifier; + #internals = new Map([ + ['settings', new Map()], + ]); + + /** + * Constructs a new instance of the Cetra framework. + * @class + * @classdesc The Cetra framework provides a reactive approach to DOM manipulation and component management. + * @param {Map} settings - A map object containing the framework settings. + */ + constructor(options = new Map()) { + super(); + this.#identifier = this.uid(); + this.#init(); + } + + /** + * Retrieves an instance of Cetra by its ID. + * @param {string} id - The ID of the Cetra instance to retrieve. + * @returns {Cetra} The Cetra instance with the specified ID. + */ + static getInstance(id) { + return Cetra.#instances.get(id); + } + + /** + * Initializes the Cetra framework by setting up the mutation observer and processing existing components. + * @memberof Cetra + * @instance + * @method + */ + #init() { + this.#root = + this.#internals.get('settings').get('root') || + document.querySelector(this.#internals.get('settings').get('root')); + + if (typeof this.#root == 'string') { + this.#root = document.querySelector(this.#root); + + if (!this.#root) { + Logger.error('No root found, defaulting to body'); + this.#root = document.body; + } + } + + this.#registerDefaults(); + + this.#root.setAttribute( + `data-${this.#internals.get('settings').get('selector')}-id`, + this.#identifier + ); + + Cetra.#instances.set(this.#identifier, this); + this.emit('afterInit', this); + } + + /** + * Registers default properties, transformer or anything related to the functionality + * @returns {void} + */ + #registerDefaults() { + } + + /** + * checks if the given url is valid + * @param {String} url the url to check + * @returns {Boolean} true if the url is valid, false otherwise + */ + #isUrl(url) { + if (typeof url != 'string') return false; + try { + // if there is no error this should be a valid url + const urlObj = new URL(url, window.location.href); + return this.#internals.get('settings').get('enforceSecureUrls') + ? urlObj.protocol === 'https:' + : true; + } catch (err) { + // any error is a bad url + return false; + } + } + + /** + * Generates a (internally)unique identifier. + * @param {number} [numGroups=1] - The number of groups to generate. + * @param {number} [groupLength=6] - The length of each group. + * @memberof Cetra + * @method + * @returns {string} The unique identifier. + */ + uid(numGroups = 1, groupLength = 6) { + const usedIds = new Set(Cetra.#uidIndex.values()); + + let uid = undefined; + + while (!uid || usedIds.has(uid)) { + uid = Array.from(Array(numGroups), () => + Math.random() + .toString(36) + .substring(2, groupLength + 2) + ).join(''); + } + + Cetra.#uidIndex.add(uid); + + return uid; + } + + /** + * Retrieves the value of the specified option from the framework's settings. + * @memberof Cetra + * @instance + * @method + * @param {string} option - The name of the option to retrieve. + * @returns {*} The value of the specified option. + */ + getOption(key) { + if (typeof key != 'string') + throw new Error('given key is not a string!'); + return this.#internals + .get('settings') + .get(key.toString().toLowerCase()); + } +} + +export default Cetra; diff --git a/lib/lib.js b/lib/lib.js new file mode 100644 index 0000000..6086729 --- /dev/null +++ b/lib/lib.js @@ -0,0 +1,3 @@ +import Cetra from "./core/Cetra"; + +export default Cetra; \ No newline at end of file