diff --git a/.obsidian/community-plugins.json b/.obsidian/community-plugins.json index 6de9bccb..e65c8de7 100644 --- a/.obsidian/community-plugins.json +++ b/.obsidian/community-plugins.json @@ -41,5 +41,7 @@ "oz-image-plugin", "file-tree-alternative", "obsidian-apple-reminders-plugin", - "hidden-folder-obsidian" + "hidden-folder-obsidian", + "tag-wrangler", + "colored-tags" ] \ No newline at end of file diff --git a/.obsidian/plugins/colored-tags/data.json b/.obsidian/plugins/colored-tags/data.json new file mode 100644 index 00000000..0c910857 --- /dev/null +++ b/.obsidian/plugins/colored-tags/data.json @@ -0,0 +1,36 @@ +{ + "palette": { + "seed": 0, + "selected": "adaptive-soft", + "custom": "e12729-f37324-f8cc1b-72b043-007f4e" + }, + "mixColors": true, + "transition": true, + "accessibility": { + "highTextContrast": false + }, + "knownTags": { + "dailynote": 1, + "memos": 2, + "telegrambot": 3, + "桥牌": 4, + "obsidian入门": 5, + "ppt": 6, + "obsidian读文献": 7, + "obsidian附录": 8, + "weeklynote": 9, + "monthly-summary": 10, + "开源": 11, + "clippings": 12, + "books": 13, + "标签": 14, + "我的实习求职记录": 15, + "23届找工作求助阵地": 16, + "产品知识": 17, + "产品知识/分析报告": 1, + "产品知识/分析报告/竞品分析": 1, + "ps": 18, + "知识库": 19 + }, + "_version": 3 +} \ No newline at end of file diff --git a/.obsidian/plugins/colored-tags/main.js b/.obsidian/plugins/colored-tags/main.js new file mode 100644 index 00000000..a2d57973 --- /dev/null +++ b/.obsidian/plugins/colored-tags/main.js @@ -0,0 +1,3776 @@ +/* +THIS IS A GENERATED/BUNDLED FILE BY ESBUILD +if you want to view the source, please visit the github repository of this plugin +*/ + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to2, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to2, key) && key !== except) + __defProp(to2, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to2; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); +var __publicField = (obj, key, value) => { + __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); + return value; +}; + +// src/main.ts +var main_exports = {}; +__export(main_exports, { + default: () => ColoredTagsPlugin +}); +module.exports = __toCommonJS(main_exports); +var import_obsidian2 = require("obsidian"); + +// node_modules/colorjs.io/dist/color.js +function multiplyMatrices(A, B) { + let m3 = A.length; + if (!Array.isArray(A[0])) { + A = [A]; + } + if (!Array.isArray(B[0])) { + B = B.map((x) => [x]); + } + let p2 = B[0].length; + let B_cols = B[0].map((_, i) => B.map((x) => x[i])); + let product = A.map((row) => B_cols.map((col) => { + let ret = 0; + if (!Array.isArray(row)) { + for (let c4 of col) { + ret += row * c4; + } + return ret; + } + for (let i = 0; i < row.length; i++) { + ret += row[i] * (col[i] || 0); + } + return ret; + })); + if (m3 === 1) { + product = product[0]; + } + if (p2 === 1) { + return product.map((x) => x[0]); + } + return product; +} +function isString(str) { + return type(str) === "string"; +} +function type(o) { + let str = Object.prototype.toString.call(o); + return (str.match(/^\[object\s+(.*?)\]$/)[1] || "").toLowerCase(); +} +function toPrecision(n2, precision) { + n2 = +n2; + precision = +precision; + let integerLength = (Math.floor(n2) + "").length; + if (precision > integerLength) { + return +n2.toFixed(precision - integerLength); + } else { + let p10 = 10 ** (integerLength - precision); + return Math.round(n2 / p10) * p10; + } +} +function parseFunction(str) { + if (!str) { + return; + } + str = str.trim(); + const isFunctionRegex = /^([a-z]+)\((.+?)\)$/i; + const isNumberRegex = /^-?[\d.]+$/; + let parts = str.match(isFunctionRegex); + if (parts) { + let args = []; + parts[2].replace(/\/?\s*([-\w.]+(?:%|deg)?)/g, ($0, arg) => { + if (/%$/.test(arg)) { + arg = new Number(arg.slice(0, -1) / 100); + arg.type = ""; + } else if (/deg$/.test(arg)) { + arg = new Number(+arg.slice(0, -3)); + arg.type = ""; + arg.unit = "deg"; + } else if (isNumberRegex.test(arg)) { + arg = new Number(arg); + arg.type = ""; + } + if ($0.startsWith("/")) { + arg = arg instanceof Number ? arg : new Number(arg); + arg.alpha = true; + } + args.push(arg); + }); + return { + name: parts[1].toLowerCase(), + rawName: parts[1], + rawArgs: parts[2], + // An argument could be (as of css-color-4): + // a number, percentage, degrees (hue), ident (in color()) + args + }; + } +} +function last(arr) { + return arr[arr.length - 1]; +} +function interpolate(start, end, p2) { + if (isNaN(start)) { + return end; + } + if (isNaN(end)) { + return start; + } + return start + (end - start) * p2; +} +function interpolateInv(start, end, value) { + return (value - start) / (end - start); +} +function mapRange(from, to2, value) { + return interpolate(to2[0], to2[1], interpolateInv(from[0], from[1], value)); +} +function parseCoordGrammar(coordGrammars) { + return coordGrammars.map((coordGrammar2) => { + return coordGrammar2.split("|").map((type2) => { + type2 = type2.trim(); + let range2 = type2.match(/^(<[a-z]+>)\[(-?[.\d]+),\s*(-?[.\d]+)\]?$/); + if (range2) { + let ret = new String(range2[1]); + ret.range = [+range2[2], +range2[3]]; + return ret; + } + return type2; + }); + }); +} +var util = /* @__PURE__ */ Object.freeze({ + __proto__: null, + interpolate, + interpolateInv, + isString, + last, + mapRange, + multiplyMatrices, + parseCoordGrammar, + parseFunction, + toPrecision, + type +}); +var Hooks = class { + add(name, callback, first) { + if (typeof arguments[0] != "string") { + for (var name in arguments[0]) { + this.add(name, arguments[0][name], arguments[1]); + } + return; + } + (Array.isArray(name) ? name : [name]).forEach(function(name2) { + this[name2] = this[name2] || []; + if (callback) { + this[name2][first ? "unshift" : "push"](callback); + } + }, this); + } + run(name, env) { + this[name] = this[name] || []; + this[name].forEach(function(callback) { + callback.call(env && env.context ? env.context : env, env); + }); + } +}; +var hooks = new Hooks(); +var defaults = { + gamut_mapping: "lch.c", + precision: 5, + deltaE: "76" + // Default deltaE method +}; +var WHITES = { + // for compatibility, the four-digit chromaticity-derived ones everyone else uses + D50: [0.3457 / 0.3585, 1, (1 - 0.3457 - 0.3585) / 0.3585], + D65: [0.3127 / 0.329, 1, (1 - 0.3127 - 0.329) / 0.329] +}; +function getWhite(name) { + if (Array.isArray(name)) { + return name; + } + return WHITES[name]; +} +function adapt$1(W1, W2, XYZ, options = {}) { + W1 = getWhite(W1); + W2 = getWhite(W2); + if (!W1 || !W2) { + throw new TypeError(`Missing white point to convert ${!W1 ? "from" : ""}${!W1 && !W2 ? "/" : ""}${!W2 ? "to" : ""}`); + } + if (W1 === W2) { + return XYZ; + } + let env = { W1, W2, XYZ, options }; + hooks.run("chromatic-adaptation-start", env); + if (!env.M) { + if (env.W1 === WHITES.D65 && env.W2 === WHITES.D50) { + env.M = [ + [1.0479298208405488, 0.022946793341019088, -0.05019222954313557], + [0.029627815688159344, 0.990434484573249, -0.01707382502938514], + [-0.009243058152591178, 0.015055144896577895, 0.7518742899580008] + ]; + } else if (env.W1 === WHITES.D50 && env.W2 === WHITES.D65) { + env.M = [ + [0.9554734527042182, -0.023098536874261423, 0.0632593086610217], + [-0.028369706963208136, 1.0099954580058226, 0.021041398966943008], + [0.012314001688319899, -0.020507696433477912, 1.3303659366080753] + ]; + } + } + hooks.run("chromatic-adaptation-end", env); + if (env.M) { + return multiplyMatrices(env.M, env.XYZ); + } else { + throw new TypeError("Only Bradford CAT with white points D50 and D65 supported for now."); + } +} +var \u03B5$4 = 75e-6; +var _ColorSpace = class { + constructor(options) { + var _a, _b, _c, _d, _e, _f, _g; + this.id = options.id; + this.name = options.name; + this.base = options.base ? _ColorSpace.get(options.base) : null; + this.aliases = options.aliases; + if (this.base) { + this.fromBase = options.fromBase; + this.toBase = options.toBase; + } + let coords = (_a = options.coords) != null ? _a : this.base.coords; + for (let name in coords) { + if (!("name" in coords[name])) { + coords[name].name = name; + } + } + this.coords = coords; + let white2 = (_c = (_b = options.white) != null ? _b : this.base.white) != null ? _c : "D65"; + this.white = getWhite(white2); + this.formats = (_d = options.formats) != null ? _d : {}; + for (let name in this.formats) { + let format = this.formats[name]; + format.type || (format.type = "function"); + format.name || (format.name = name); + } + if (options.cssId && !((_e = this.formats.functions) == null ? void 0 : _e.color)) { + this.formats.color = { id: options.cssId }; + Object.defineProperty(this, "cssId", { value: options.cssId }); + } else if (((_f = this.formats) == null ? void 0 : _f.color) && !((_g = this.formats) == null ? void 0 : _g.color.id)) { + this.formats.color.id = this.id; + } + this.referred = options.referred; + Object.defineProperty(this, "path", { + value: getPath(this).reverse(), + writable: false, + enumerable: true, + configurable: true + }); + hooks.run("colorspace-init-end", this); + } + inGamut(coords, { epsilon = \u03B5$4 } = {}) { + if (this.isPolar) { + coords = this.toBase(coords); + return this.base.inGamut(coords, { epsilon }); + } + let coordMeta = Object.values(this.coords); + return coords.every((c4, i) => { + let meta = coordMeta[i]; + if (meta.type !== "angle" && meta.range) { + if (Number.isNaN(c4)) { + return true; + } + let [min, max2] = meta.range; + return (min === void 0 || c4 >= min - epsilon) && (max2 === void 0 || c4 <= max2 + epsilon); + } + return true; + }); + } + get cssId() { + var _a, _b; + return ((_b = (_a = this.formats.functions) == null ? void 0 : _a.color) == null ? void 0 : _b.id) || this.id; + } + get isPolar() { + for (let id in this.coords) { + if (this.coords[id].type === "angle") { + return true; + } + } + return false; + } + getFormat(format) { + if (typeof format === "object") { + format = processFormat(format, this); + return format; + } + let ret; + if (format === "default") { + ret = Object.values(this.formats)[0]; + } else { + ret = this.formats[format]; + } + if (ret) { + ret = processFormat(ret, this); + return ret; + } + return null; + } + // We cannot rely on simple === because then ColorSpace objects cannot be proxied + equals(space) { + if (!space) { + return false; + } + return this === space || this.id === space.id; + } + to(space, coords) { + if (arguments.length === 1) { + [space, coords] = [space.space, space.coords]; + } + space = _ColorSpace.get(space); + if (this.equals(space)) { + return coords; + } + coords = coords.map((c4) => Number.isNaN(c4) ? 0 : c4); + let myPath = this.path; + let otherPath = space.path; + let connectionSpace, connectionSpaceIndex; + for (let i = 0; i < myPath.length; i++) { + if (myPath[i].equals(otherPath[i])) { + connectionSpace = myPath[i]; + connectionSpaceIndex = i; + } else { + break; + } + } + if (!connectionSpace) { + throw new Error(`Cannot convert between color spaces ${this} and ${space}: no connection space was found`); + } + for (let i = myPath.length - 1; i > connectionSpaceIndex; i--) { + coords = myPath[i].toBase(coords); + } + for (let i = connectionSpaceIndex + 1; i < otherPath.length; i++) { + coords = otherPath[i].fromBase(coords); + } + return coords; + } + from(space, coords) { + if (arguments.length === 1) { + [space, coords] = [space.space, space.coords]; + } + space = _ColorSpace.get(space); + return space.to(this, coords); + } + toString() { + return `${this.name} (${this.id})`; + } + getMinCoords() { + var _a; + let ret = []; + for (let id in this.coords) { + let meta = this.coords[id]; + let range2 = meta.range || meta.refRange; + ret.push((_a = range2 == null ? void 0 : range2.min) != null ? _a : 0); + } + return ret; + } + // Returns array of unique color spaces + static get all() { + return [...new Set(Object.values(_ColorSpace.registry))]; + } + static register(id, space) { + if (arguments.length === 1) { + space = arguments[0]; + id = space.id; + } + space = this.get(space); + if (this.registry[id] && this.registry[id] !== space) { + throw new Error(`Duplicate color space registration: '${id}'`); + } + this.registry[id] = space; + if (arguments.length === 1 && space.aliases) { + for (let alias of space.aliases) { + this.register(alias, space); + } + } + return space; + } + /** + * Lookup ColorSpace object by name + * @param {ColorSpace | string} name + */ + static get(space, ...alternatives) { + if (!space || space instanceof _ColorSpace) { + return space; + } + let argType = type(space); + if (argType === "string") { + let ret = _ColorSpace.registry[space.toLowerCase()]; + if (!ret) { + throw new TypeError(`No color space found with id = "${space}"`); + } + return ret; + } + if (alternatives.length) { + return _ColorSpace.get(...alternatives); + } + throw new TypeError(`${space} is not a valid color space`); + } + /** + * Get metadata about a coordinate of a color space + * + * @static + * @param {Array | string} ref + * @param {ColorSpace | string} [workingSpace] + * @return {Object} + */ + static resolveCoord(ref, workingSpace) { + var _a; + let coordType = type(ref); + let space, coord; + if (coordType === "string") { + if (ref.includes(".")) { + [space, coord] = ref.split("."); + } else { + [space, coord] = [, ref]; + } + } else if (Array.isArray(ref)) { + [space, coord] = ref; + } else { + space = ref.space; + coord = ref.coordId; + } + space = _ColorSpace.get(space); + if (!space) { + space = workingSpace; + } + if (!space) { + throw new TypeError(`Cannot resolve coordinate reference ${ref}: No color space specified and relative references are not allowed here`); + } + coordType = type(coord); + if (coordType === "number" || coordType === "string" && coord >= 0) { + let meta = Object.entries(space.coords)[coord]; + if (meta) { + return { space, id: meta[0], index: coord, ...meta[1] }; + } + } + space = _ColorSpace.get(space); + let normalizedCoord = coord.toLowerCase(); + let i = 0; + for (let id in space.coords) { + let meta = space.coords[id]; + if (id.toLowerCase() === normalizedCoord || ((_a = meta.name) == null ? void 0 : _a.toLowerCase()) === normalizedCoord) { + return { space, id, index: i, ...meta }; + } + i++; + } + throw new TypeError(`No "${coord}" coordinate found in ${space.name}. Its coordinates are: ${Object.keys(space.coords).join(", ")}`); + } +}; +var ColorSpace = _ColorSpace; +__publicField(ColorSpace, "registry", {}); +__publicField(ColorSpace, "DEFAULT_FORMAT", { + type: "functions", + name: "color" +}); +function getPath(space) { + let ret = [space]; + for (let s = space; s = s.base; ) { + ret.push(s); + } + return ret; +} +function processFormat(format, { coords } = {}) { + if (format.coords && !format.coordGrammar) { + format.type || (format.type = "function"); + format.name || (format.name = "color"); + format.coordGrammar = parseCoordGrammar(format.coords); + let coordFormats = Object.entries(coords).map(([id, coordMeta], i) => { + let outputType = format.coordGrammar[i][0]; + let fromRange = coordMeta.range || coordMeta.refRange; + let toRange = outputType.range, suffix = ""; + if (outputType == "") { + toRange = [0, 100]; + suffix = "%"; + } else if (outputType == "") { + suffix = "deg"; + } + return { fromRange, toRange, suffix }; + }); + format.serializeCoords = (coords2, precision) => { + return coords2.map((c4, i) => { + let { fromRange, toRange, suffix } = coordFormats[i]; + if (fromRange && toRange) { + c4 = mapRange(fromRange, toRange, c4); + } + c4 = toPrecision(c4, precision); + if (suffix) { + c4 += suffix; + } + return c4; + }); + }; + } + return format; +} +var XYZ_D65 = new ColorSpace({ + id: "xyz-d65", + name: "XYZ D65", + coords: { + x: { name: "X" }, + y: { name: "Y" }, + z: { name: "Z" } + }, + white: "D65", + formats: { + color: { + ids: ["xyz-d65", "xyz"] + } + }, + aliases: ["xyz"] +}); +var RGBColorSpace = class extends ColorSpace { + /** + * Creates a new RGB ColorSpace. + * If coords are not specified, they will use the default RGB coords. + * Instead of `fromBase()` and `toBase()` functions, + * you can specify to/from XYZ matrices and have `toBase()` and `fromBase()` automatically generated. + * @param {*} options - Same options as {@link ColorSpace} plus: + * @param {number[][]} options.toXYZ_M - Matrix to convert to XYZ + * @param {number[][]} options.fromXYZ_M - Matrix to convert from XYZ + */ + constructor(options) { + var _a, _b, _c; + if (!options.coords) { + options.coords = { + r: { + range: [0, 1], + name: "Red" + }, + g: { + range: [0, 1], + name: "Green" + }, + b: { + range: [0, 1], + name: "Blue" + } + }; + } + if (!options.base) { + options.base = XYZ_D65; + } + if (options.toXYZ_M && options.fromXYZ_M) { + (_a = options.toBase) != null ? _a : options.toBase = (rgb) => { + let xyz = multiplyMatrices(options.toXYZ_M, rgb); + if (this.white !== this.base.white) { + xyz = adapt$1(this.white, this.base.white, xyz); + } + return xyz; + }; + (_b = options.fromBase) != null ? _b : options.fromBase = (xyz) => { + xyz = adapt$1(this.base.white, this.white, xyz); + return multiplyMatrices(options.fromXYZ_M, xyz); + }; + } + (_c = options.referred) != null ? _c : options.referred = "display"; + super(options); + } +}; +function parse(str, { meta } = {}) { + var _a, _b, _c, _d, _e, _f; + let env = { "str": (_a = String(str)) == null ? void 0 : _a.trim() }; + hooks.run("parse-start", env); + if (env.color) { + return env.color; + } + env.parsed = parseFunction(env.str); + if (env.parsed) { + let name = env.parsed.name; + if (name === "color") { + let id = env.parsed.args.shift(); + let alpha = env.parsed.rawArgs.indexOf("/") > 0 ? env.parsed.args.pop() : 1; + for (let space of ColorSpace.all) { + let colorSpec = space.getFormat("color"); + if (colorSpec) { + if (id === colorSpec.id || ((_b = colorSpec.ids) == null ? void 0 : _b.includes(id))) { + const coords = Object.keys(space.coords).map((_, i) => env.parsed.args[i] || 0); + if (meta) { + meta.formatId = "color"; + } + return { spaceId: space.id, coords, alpha }; + } + } + } + let didYouMean = ""; + if (id in ColorSpace.registry) { + let cssId = (_e = (_d = (_c = ColorSpace.registry[id].formats) == null ? void 0 : _c.functions) == null ? void 0 : _d.color) == null ? void 0 : _e.id; + if (cssId) { + didYouMean = `Did you mean color(${cssId})?`; + } + } + throw new TypeError(`Cannot parse color(${id}). ` + (didYouMean || "Missing a plugin?")); + } else { + for (let space of ColorSpace.all) { + let format = space.getFormat(name); + if (format && format.type === "function") { + let alpha = 1; + if (format.lastAlpha || last(env.parsed.args).alpha) { + alpha = env.parsed.args.pop(); + } + let coords = env.parsed.args; + let types; + if (format.coordGrammar) { + types = Object.entries(space.coords).map(([id, coordMeta], i) => { + var _a2; + let coordGrammar2 = format.coordGrammar[i]; + let providedType = (_a2 = coords[i]) == null ? void 0 : _a2.type; + let type2 = coordGrammar2.find((c4) => c4 == providedType); + if (!type2) { + let coordName = coordMeta.name || id; + throw new TypeError(`${providedType} not allowed for ${coordName} in ${name}()`); + } + let fromRange = type2.range; + if (providedType === "") { + fromRange || (fromRange = [0, 1]); + } + let toRange = coordMeta.range || coordMeta.refRange; + if (fromRange && toRange) { + coords[i] = mapRange(fromRange, toRange, coords[i]); + } + return type2; + }); + } + if (meta) { + Object.assign(meta, { formatId: format.name, types }); + } + return { + spaceId: space.id, + coords, + alpha + }; + } + } + } + } else { + for (let space of ColorSpace.all) { + for (let formatId in space.formats) { + let format = space.formats[formatId]; + if (format.type !== "custom") { + continue; + } + if (format.test && !format.test(env.str)) { + continue; + } + let color = format.parse(env.str); + if (color) { + (_f = color.alpha) != null ? _f : color.alpha = 1; + if (meta) { + meta.formatId = formatId; + } + return color; + } + } + } + } + throw new TypeError(`Could not parse ${str} as a color. Missing a plugin?`); +} +function getColor(color) { + if (!color) { + throw new TypeError("Empty color reference"); + } + if (isString(color)) { + color = parse(color); + } + let space = color.space || color.spaceId; + if (!(space instanceof ColorSpace)) { + color.space = ColorSpace.get(space); + } + if (color.alpha === void 0) { + color.alpha = 1; + } + return color; +} +function getAll(color, space) { + space = ColorSpace.get(space); + return space.from(color); +} +function get(color, prop) { + let { space, index } = ColorSpace.resolveCoord(prop, color.space); + let coords = getAll(color, space); + return coords[index]; +} +function setAll(color, space, coords) { + space = ColorSpace.get(space); + color.coords = space.to(color.space, coords); + return color; +} +function set(color, prop, value) { + color = getColor(color); + if (arguments.length === 2 && type(arguments[1]) === "object") { + let object = arguments[1]; + for (let p2 in object) { + set(color, p2, object[p2]); + } + } else { + if (typeof value === "function") { + value = value(get(color, prop)); + } + let { space, index } = ColorSpace.resolveCoord(prop, color.space); + let coords = getAll(color, space); + coords[index] = value; + setAll(color, space, coords); + } + return color; +} +var XYZ_D50 = new ColorSpace({ + id: "xyz-d50", + name: "XYZ D50", + white: "D50", + base: XYZ_D65, + fromBase: (coords) => adapt$1(XYZ_D65.white, "D50", coords), + toBase: (coords) => adapt$1("D50", XYZ_D65.white, coords), + formats: { + color: {} + } +}); +var \u03B5$3 = 216 / 24389; +var \u03B53$1 = 24 / 116; +var \u03BA$1 = 24389 / 27; +var white$1 = WHITES.D50; +var lab = new ColorSpace({ + id: "lab", + name: "Lab", + coords: { + l: { + refRange: [0, 100], + name: "L" + }, + a: { + refRange: [-125, 125] + }, + b: { + refRange: [-125, 125] + } + }, + // Assuming XYZ is relative to D50, convert to CIE Lab + // from CIE standard, which now defines these as a rational fraction + white: white$1, + base: XYZ_D50, + // Convert D50-adapted XYX to Lab + // CIE 15.3:2004 section 8.2.1.1 + fromBase(XYZ) { + let xyz = XYZ.map((value, i) => value / white$1[i]); + let f = xyz.map((value) => value > \u03B5$3 ? Math.cbrt(value) : (\u03BA$1 * value + 16) / 116); + return [ + 116 * f[1] - 16, + // L + 500 * (f[0] - f[1]), + // a + 200 * (f[1] - f[2]) + // b + ]; + }, + // Convert Lab to D50-adapted XYZ + // Same result as CIE 15.3:2004 Appendix D although the derivation is different + // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html + toBase(Lab) { + let f = []; + f[1] = (Lab[0] + 16) / 116; + f[0] = Lab[1] / 500 + f[1]; + f[2] = f[1] - Lab[2] / 200; + let xyz = [ + f[0] > \u03B53$1 ? Math.pow(f[0], 3) : (116 * f[0] - 16) / \u03BA$1, + Lab[0] > 8 ? Math.pow((Lab[0] + 16) / 116, 3) : Lab[0] / \u03BA$1, + f[2] > \u03B53$1 ? Math.pow(f[2], 3) : (116 * f[2] - 16) / \u03BA$1 + ]; + return xyz.map((value, i) => value * white$1[i]); + }, + formats: { + "lab": { + coords: [" | ", " | [-1,1]", " | [-1,1]"] + } + } +}); +function constrain(angle) { + return (angle % 360 + 360) % 360; +} +function adjust(arc, angles) { + if (arc === "raw") { + return angles; + } + let [a1, a2] = angles.map(constrain); + let angleDiff = a2 - a1; + if (arc === "increasing") { + if (angleDiff < 0) { + a2 += 360; + } + } else if (arc === "decreasing") { + if (angleDiff > 0) { + a1 += 360; + } + } else if (arc === "longer") { + if (-180 < angleDiff && angleDiff < 180) { + if (angleDiff > 0) { + a1 += 360; + } else { + a2 += 360; + } + } + } else if (arc === "shorter") { + if (angleDiff > 180) { + a1 += 360; + } else if (angleDiff < -180) { + a2 += 360; + } + } + return [a1, a2]; +} +var lch = new ColorSpace({ + id: "lch", + name: "LCH", + coords: { + l: { + refRange: [0, 100], + name: "Lightness" + }, + c: { + refRange: [0, 150], + name: "Chroma" + }, + h: { + refRange: [0, 360], + type: "angle", + name: "Hue" + } + }, + base: lab, + fromBase(Lab) { + let [L, a2, b2] = Lab; + let hue; + const \u03B52 = 0.02; + if (Math.abs(a2) < \u03B52 && Math.abs(b2) < \u03B52) { + hue = NaN; + } else { + hue = Math.atan2(b2, a2) * 180 / Math.PI; + } + return [ + L, + // L is still L + Math.sqrt(a2 ** 2 + b2 ** 2), + // Chroma + constrain(hue) + // Hue, in degrees [0 to 360) + ]; + }, + toBase(LCH) { + let [Lightness, Chroma, Hue] = LCH; + if (Chroma < 0) { + Chroma = 0; + } + if (isNaN(Hue)) { + Hue = 0; + } + return [ + Lightness, + // L is still L + Chroma * Math.cos(Hue * Math.PI / 180), + // a + Chroma * Math.sin(Hue * Math.PI / 180) + // b + ]; + }, + formats: { + "lch": { + coords: [" | ", " | ", " | "] + } + } +}); +var Gfactor = 25 ** 7; +var \u03C0$1 = Math.PI; +var r2d = 180 / \u03C0$1; +var d2r$1 = \u03C0$1 / 180; +function deltaE2000(color, sample, { kL = 1, kC = 1, kH = 1 } = {}) { + let [L1, a1, b1] = lab.from(color); + let C1 = lch.from(lab, [L1, a1, b1])[1]; + let [L2, a2, b2] = lab.from(sample); + let C2 = lch.from(lab, [L2, a2, b2])[1]; + if (C1 < 0) { + C1 = 0; + } + if (C2 < 0) { + C2 = 0; + } + let Cbar = (C1 + C2) / 2; + let C7 = Cbar ** 7; + let G = 0.5 * (1 - Math.sqrt(C7 / (C7 + Gfactor))); + let adash1 = (1 + G) * a1; + let adash2 = (1 + G) * a2; + let Cdash1 = Math.sqrt(adash1 ** 2 + b1 ** 2); + let Cdash2 = Math.sqrt(adash2 ** 2 + b2 ** 2); + let h1 = adash1 === 0 && b1 === 0 ? 0 : Math.atan2(b1, adash1); + let h2 = adash2 === 0 && b2 === 0 ? 0 : Math.atan2(b2, adash2); + if (h1 < 0) { + h1 += 2 * \u03C0$1; + } + if (h2 < 0) { + h2 += 2 * \u03C0$1; + } + h1 *= r2d; + h2 *= r2d; + let \u0394L = L2 - L1; + let \u0394C = Cdash2 - Cdash1; + let hdiff = h2 - h1; + let hsum = h1 + h2; + let habs = Math.abs(hdiff); + let \u0394h; + if (Cdash1 * Cdash2 === 0) { + \u0394h = 0; + } else if (habs <= 180) { + \u0394h = hdiff; + } else if (hdiff > 180) { + \u0394h = hdiff - 360; + } else if (hdiff < -180) { + \u0394h = hdiff + 360; + } else { + console.log("the unthinkable has happened"); + } + let \u0394H = 2 * Math.sqrt(Cdash2 * Cdash1) * Math.sin(\u0394h * d2r$1 / 2); + let Ldash = (L1 + L2) / 2; + let Cdash = (Cdash1 + Cdash2) / 2; + let Cdash7 = Math.pow(Cdash, 7); + let hdash; + if (Cdash1 * Cdash2 === 0) { + hdash = hsum; + } else if (habs <= 180) { + hdash = hsum / 2; + } else if (hsum < 360) { + hdash = (hsum + 360) / 2; + } else { + hdash = (hsum - 360) / 2; + } + let lsq = (Ldash - 50) ** 2; + let SL = 1 + 0.015 * lsq / Math.sqrt(20 + lsq); + let SC = 1 + 0.045 * Cdash; + let T = 1; + T -= 0.17 * Math.cos((hdash - 30) * d2r$1); + T += 0.24 * Math.cos(2 * hdash * d2r$1); + T += 0.32 * Math.cos((3 * hdash + 6) * d2r$1); + T -= 0.2 * Math.cos((4 * hdash - 63) * d2r$1); + let SH = 1 + 0.015 * Cdash * T; + let \u0394\u03B8 = 30 * Math.exp(-1 * ((hdash - 275) / 25) ** 2); + let RC = 2 * Math.sqrt(Cdash7 / (Cdash7 + Gfactor)); + let RT = -1 * Math.sin(2 * \u0394\u03B8 * d2r$1) * RC; + let dE = (\u0394L / (kL * SL)) ** 2; + dE += (\u0394C / (kC * SC)) ** 2; + dE += (\u0394H / (kH * SH)) ** 2; + dE += RT * (\u0394C / (kC * SC)) * (\u0394H / (kH * SH)); + return Math.sqrt(dE); +} +var \u03B5$2 = 75e-6; +function inGamut(color, space = color.space, { epsilon = \u03B5$2 } = {}) { + color = getColor(color); + space = ColorSpace.get(space); + let coords = color.coords; + if (space !== color.space) { + coords = space.from(color); + } + return space.inGamut(coords, { epsilon }); +} +function clone(color) { + return { + space: color.space, + coords: color.coords.slice(), + alpha: color.alpha + }; +} +function toGamut(color, { method = defaults.gamut_mapping, space = color.space } = {}) { + if (isString(arguments[1])) { + space = arguments[1]; + } + space = ColorSpace.get(space); + if (inGamut(color, space, { epsilon: 0 })) { + return getColor(color); + } + let spaceColor = to(color, space); + if (method !== "clip" && !inGamut(color, space)) { + let clipped = toGamut(clone(spaceColor), { method: "clip", space }); + if (deltaE2000(color, clipped) > 2) { + let coordMeta = ColorSpace.resolveCoord(method); + let mapSpace = coordMeta.space; + let coordId = coordMeta.id; + let mappedColor = to(spaceColor, mapSpace); + let bounds = coordMeta.range || coordMeta.refRange; + let min = bounds[0]; + let \u03B52 = 0.01; + let low = min; + let high = get(mappedColor, coordId); + while (high - low > \u03B52) { + let clipped2 = clone(mappedColor); + clipped2 = toGamut(clipped2, { space, method: "clip" }); + let deltaE2 = deltaE2000(mappedColor, clipped2); + if (deltaE2 - 2 < \u03B52) { + low = get(mappedColor, coordId); + } else { + high = get(mappedColor, coordId); + } + set(mappedColor, coordId, (low + high) / 2); + } + spaceColor = to(mappedColor, space); + } else { + spaceColor = clipped; + } + } + if (method === "clip" || !inGamut(spaceColor, space, { epsilon: 0 })) { + let bounds = Object.values(space.coords).map((c4) => c4.range || []); + spaceColor.coords = spaceColor.coords.map((c4, i) => { + let [min, max2] = bounds[i]; + if (min !== void 0) { + c4 = Math.max(min, c4); + } + if (max2 !== void 0) { + c4 = Math.min(c4, max2); + } + return c4; + }); + } + if (space !== color.space) { + spaceColor = to(spaceColor, color.space); + } + color.coords = spaceColor.coords; + return color; +} +toGamut.returns = "color"; +function to(color, space, { inGamut: inGamut2 } = {}) { + color = getColor(color); + space = ColorSpace.get(space); + let coords = space.from(color); + let ret = { space, coords, alpha: color.alpha }; + if (inGamut2) { + ret = toGamut(ret); + } + return ret; +} +to.returns = "color"; +function serialize(color, { + precision = defaults.precision, + format = "default", + inGamut: inGamut$1 = true, + ...customOptions +} = {}) { + var _a, _b, _c; + let ret; + color = getColor(color); + let formatId = format; + format = (_b = (_a = color.space.getFormat(format)) != null ? _a : color.space.getFormat("default")) != null ? _b : ColorSpace.DEFAULT_FORMAT; + inGamut$1 || (inGamut$1 = format.toGamut); + let coords = color.coords; + coords = coords.map((c4) => c4 ? c4 : 0); + if (inGamut$1 && !inGamut(color)) { + coords = toGamut(clone(color), inGamut$1 === true ? void 0 : inGamut$1).coords; + } + if (format.type === "custom") { + customOptions.precision = precision; + if (format.serialize) { + ret = format.serialize(coords, color.alpha, customOptions); + } else { + throw new TypeError(`format ${formatId} can only be used to parse colors, not for serialization`); + } + } else { + let name = format.name || "color"; + if (format.serializeCoords) { + coords = format.serializeCoords(coords, precision); + } else { + if (precision !== null) { + coords = coords.map((c4) => toPrecision(c4, precision)); + } + } + let args = [...coords]; + if (name === "color") { + let cssId = format.id || ((_c = format.ids) == null ? void 0 : _c[0]) || color.space.id; + args.unshift(cssId); + } + let alpha = color.alpha; + if (precision !== null) { + alpha = toPrecision(alpha, precision); + } + let strAlpha = color.alpha < 1 && !format.noAlpha ? `${format.commas ? "," : " /"} ${alpha}` : ""; + ret = `${name}(${args.join(format.commas ? ", " : " ")}${strAlpha})`; + } + return ret; +} +var toXYZ_M$5 = [ + [0.6369580483012914, 0.14461690358620832, 0.1688809751641721], + [0.2627002120112671, 0.6779980715188708, 0.05930171646986196], + [0, 0.028072693049087428, 1.060985057710791] +]; +var fromXYZ_M$5 = [ + [1.716651187971268, -0.355670783776392, -0.25336628137366], + [-0.666684351832489, 1.616481236634939, 0.0157685458139111], + [0.017639857445311, -0.042770613257809, 0.942103121235474] +]; +var REC2020Linear = new RGBColorSpace({ + id: "rec2020-linear", + name: "Linear REC.2020", + white: "D65", + toXYZ_M: toXYZ_M$5, + fromXYZ_M: fromXYZ_M$5, + formats: { + color: {} + } +}); +var \u03B1 = 1.09929682680944; +var \u03B2 = 0.018053968510807; +var REC2020 = new RGBColorSpace({ + id: "rec2020", + name: "REC.2020", + base: REC2020Linear, + // Non-linear transfer function from Rec. ITU-R BT.2020-2 table 4 + toBase(RGB) { + return RGB.map(function(val) { + if (val < \u03B2 * 4.5) { + return val / 4.5; + } + return Math.pow((val + \u03B1 - 1) / \u03B1, 1 / 0.45); + }); + }, + fromBase(RGB) { + return RGB.map(function(val) { + if (val >= \u03B2) { + return \u03B1 * Math.pow(val, 0.45) - (\u03B1 - 1); + } + return 4.5 * val; + }); + }, + formats: { + color: {} + } +}); +var toXYZ_M$4 = [ + [0.4865709486482162, 0.26566769316909306, 0.1982172852343625], + [0.2289745640697488, 0.6917385218365064, 0.079286914093745], + [0, 0.04511338185890264, 1.043944368900976] +]; +var fromXYZ_M$4 = [ + [2.493496911941425, -0.9313836179191239, -0.40271078445071684], + [-0.8294889695615747, 1.7626640603183463, 0.023624685841943577], + [0.03584583024378447, -0.07617238926804182, 0.9568845240076872] +]; +var P3Linear = new RGBColorSpace({ + id: "p3-linear", + name: "Linear P3", + white: "D65", + toXYZ_M: toXYZ_M$4, + fromXYZ_M: fromXYZ_M$4 +}); +var toXYZ_M$3 = [ + [0.41239079926595934, 0.357584339383878, 0.1804807884018343], + [0.21263900587151027, 0.715168678767756, 0.07219231536073371], + [0.01933081871559182, 0.11919477979462598, 0.9505321522496607] +]; +var fromXYZ_M$3 = [ + [3.2409699419045226, -1.537383177570094, -0.4986107602930034], + [-0.9692436362808796, 1.8759675015077202, 0.04155505740717559], + [0.05563007969699366, -0.20397695888897652, 1.0569715142428786] +]; +var sRGBLinear = new RGBColorSpace({ + id: "srgb-linear", + name: "Linear sRGB", + white: "D65", + toXYZ_M: toXYZ_M$3, + fromXYZ_M: fromXYZ_M$3, + formats: { + color: {} + } +}); +var KEYWORDS = { + "aliceblue": [240 / 255, 248 / 255, 1], + "antiquewhite": [250 / 255, 235 / 255, 215 / 255], + "aqua": [0, 1, 1], + "aquamarine": [127 / 255, 1, 212 / 255], + "azure": [240 / 255, 1, 1], + "beige": [245 / 255, 245 / 255, 220 / 255], + "bisque": [1, 228 / 255, 196 / 255], + "black": [0, 0, 0], + "blanchedalmond": [1, 235 / 255, 205 / 255], + "blue": [0, 0, 1], + "blueviolet": [138 / 255, 43 / 255, 226 / 255], + "brown": [165 / 255, 42 / 255, 42 / 255], + "burlywood": [222 / 255, 184 / 255, 135 / 255], + "cadetblue": [95 / 255, 158 / 255, 160 / 255], + "chartreuse": [127 / 255, 1, 0], + "chocolate": [210 / 255, 105 / 255, 30 / 255], + "coral": [1, 127 / 255, 80 / 255], + "cornflowerblue": [100 / 255, 149 / 255, 237 / 255], + "cornsilk": [1, 248 / 255, 220 / 255], + "crimson": [220 / 255, 20 / 255, 60 / 255], + "cyan": [0, 1, 1], + "darkblue": [0, 0, 139 / 255], + "darkcyan": [0, 139 / 255, 139 / 255], + "darkgoldenrod": [184 / 255, 134 / 255, 11 / 255], + "darkgray": [169 / 255, 169 / 255, 169 / 255], + "darkgreen": [0, 100 / 255, 0], + "darkgrey": [169 / 255, 169 / 255, 169 / 255], + "darkkhaki": [189 / 255, 183 / 255, 107 / 255], + "darkmagenta": [139 / 255, 0, 139 / 255], + "darkolivegreen": [85 / 255, 107 / 255, 47 / 255], + "darkorange": [1, 140 / 255, 0], + "darkorchid": [153 / 255, 50 / 255, 204 / 255], + "darkred": [139 / 255, 0, 0], + "darksalmon": [233 / 255, 150 / 255, 122 / 255], + "darkseagreen": [143 / 255, 188 / 255, 143 / 255], + "darkslateblue": [72 / 255, 61 / 255, 139 / 255], + "darkslategray": [47 / 255, 79 / 255, 79 / 255], + "darkslategrey": [47 / 255, 79 / 255, 79 / 255], + "darkturquoise": [0, 206 / 255, 209 / 255], + "darkviolet": [148 / 255, 0, 211 / 255], + "deeppink": [1, 20 / 255, 147 / 255], + "deepskyblue": [0, 191 / 255, 1], + "dimgray": [105 / 255, 105 / 255, 105 / 255], + "dimgrey": [105 / 255, 105 / 255, 105 / 255], + "dodgerblue": [30 / 255, 144 / 255, 1], + "firebrick": [178 / 255, 34 / 255, 34 / 255], + "floralwhite": [1, 250 / 255, 240 / 255], + "forestgreen": [34 / 255, 139 / 255, 34 / 255], + "fuchsia": [1, 0, 1], + "gainsboro": [220 / 255, 220 / 255, 220 / 255], + "ghostwhite": [248 / 255, 248 / 255, 1], + "gold": [1, 215 / 255, 0], + "goldenrod": [218 / 255, 165 / 255, 32 / 255], + "gray": [128 / 255, 128 / 255, 128 / 255], + "green": [0, 128 / 255, 0], + "greenyellow": [173 / 255, 1, 47 / 255], + "grey": [128 / 255, 128 / 255, 128 / 255], + "honeydew": [240 / 255, 1, 240 / 255], + "hotpink": [1, 105 / 255, 180 / 255], + "indianred": [205 / 255, 92 / 255, 92 / 255], + "indigo": [75 / 255, 0, 130 / 255], + "ivory": [1, 1, 240 / 255], + "khaki": [240 / 255, 230 / 255, 140 / 255], + "lavender": [230 / 255, 230 / 255, 250 / 255], + "lavenderblush": [1, 240 / 255, 245 / 255], + "lawngreen": [124 / 255, 252 / 255, 0], + "lemonchiffon": [1, 250 / 255, 205 / 255], + "lightblue": [173 / 255, 216 / 255, 230 / 255], + "lightcoral": [240 / 255, 128 / 255, 128 / 255], + "lightcyan": [224 / 255, 1, 1], + "lightgoldenrodyellow": [250 / 255, 250 / 255, 210 / 255], + "lightgray": [211 / 255, 211 / 255, 211 / 255], + "lightgreen": [144 / 255, 238 / 255, 144 / 255], + "lightgrey": [211 / 255, 211 / 255, 211 / 255], + "lightpink": [1, 182 / 255, 193 / 255], + "lightsalmon": [1, 160 / 255, 122 / 255], + "lightseagreen": [32 / 255, 178 / 255, 170 / 255], + "lightskyblue": [135 / 255, 206 / 255, 250 / 255], + "lightslategray": [119 / 255, 136 / 255, 153 / 255], + "lightslategrey": [119 / 255, 136 / 255, 153 / 255], + "lightsteelblue": [176 / 255, 196 / 255, 222 / 255], + "lightyellow": [1, 1, 224 / 255], + "lime": [0, 1, 0], + "limegreen": [50 / 255, 205 / 255, 50 / 255], + "linen": [250 / 255, 240 / 255, 230 / 255], + "magenta": [1, 0, 1], + "maroon": [128 / 255, 0, 0], + "mediumaquamarine": [102 / 255, 205 / 255, 170 / 255], + "mediumblue": [0, 0, 205 / 255], + "mediumorchid": [186 / 255, 85 / 255, 211 / 255], + "mediumpurple": [147 / 255, 112 / 255, 219 / 255], + "mediumseagreen": [60 / 255, 179 / 255, 113 / 255], + "mediumslateblue": [123 / 255, 104 / 255, 238 / 255], + "mediumspringgreen": [0, 250 / 255, 154 / 255], + "mediumturquoise": [72 / 255, 209 / 255, 204 / 255], + "mediumvioletred": [199 / 255, 21 / 255, 133 / 255], + "midnightblue": [25 / 255, 25 / 255, 112 / 255], + "mintcream": [245 / 255, 1, 250 / 255], + "mistyrose": [1, 228 / 255, 225 / 255], + "moccasin": [1, 228 / 255, 181 / 255], + "navajowhite": [1, 222 / 255, 173 / 255], + "navy": [0, 0, 128 / 255], + "oldlace": [253 / 255, 245 / 255, 230 / 255], + "olive": [128 / 255, 128 / 255, 0], + "olivedrab": [107 / 255, 142 / 255, 35 / 255], + "orange": [1, 165 / 255, 0], + "orangered": [1, 69 / 255, 0], + "orchid": [218 / 255, 112 / 255, 214 / 255], + "palegoldenrod": [238 / 255, 232 / 255, 170 / 255], + "palegreen": [152 / 255, 251 / 255, 152 / 255], + "paleturquoise": [175 / 255, 238 / 255, 238 / 255], + "palevioletred": [219 / 255, 112 / 255, 147 / 255], + "papayawhip": [1, 239 / 255, 213 / 255], + "peachpuff": [1, 218 / 255, 185 / 255], + "peru": [205 / 255, 133 / 255, 63 / 255], + "pink": [1, 192 / 255, 203 / 255], + "plum": [221 / 255, 160 / 255, 221 / 255], + "powderblue": [176 / 255, 224 / 255, 230 / 255], + "purple": [128 / 255, 0, 128 / 255], + "rebeccapurple": [102 / 255, 51 / 255, 153 / 255], + "red": [1, 0, 0], + "rosybrown": [188 / 255, 143 / 255, 143 / 255], + "royalblue": [65 / 255, 105 / 255, 225 / 255], + "saddlebrown": [139 / 255, 69 / 255, 19 / 255], + "salmon": [250 / 255, 128 / 255, 114 / 255], + "sandybrown": [244 / 255, 164 / 255, 96 / 255], + "seagreen": [46 / 255, 139 / 255, 87 / 255], + "seashell": [1, 245 / 255, 238 / 255], + "sienna": [160 / 255, 82 / 255, 45 / 255], + "silver": [192 / 255, 192 / 255, 192 / 255], + "skyblue": [135 / 255, 206 / 255, 235 / 255], + "slateblue": [106 / 255, 90 / 255, 205 / 255], + "slategray": [112 / 255, 128 / 255, 144 / 255], + "slategrey": [112 / 255, 128 / 255, 144 / 255], + "snow": [1, 250 / 255, 250 / 255], + "springgreen": [0, 1, 127 / 255], + "steelblue": [70 / 255, 130 / 255, 180 / 255], + "tan": [210 / 255, 180 / 255, 140 / 255], + "teal": [0, 128 / 255, 128 / 255], + "thistle": [216 / 255, 191 / 255, 216 / 255], + "tomato": [1, 99 / 255, 71 / 255], + "turquoise": [64 / 255, 224 / 255, 208 / 255], + "violet": [238 / 255, 130 / 255, 238 / 255], + "wheat": [245 / 255, 222 / 255, 179 / 255], + "white": [1, 1, 1], + "whitesmoke": [245 / 255, 245 / 255, 245 / 255], + "yellow": [1, 1, 0], + "yellowgreen": [154 / 255, 205 / 255, 50 / 255] +}; +var coordGrammar = Array(3).fill(" | [0, 255]"); +var coordGrammarNumber = Array(3).fill("[0, 255]"); +var sRGB = new RGBColorSpace({ + id: "srgb", + name: "sRGB", + base: sRGBLinear, + fromBase: (rgb) => { + return rgb.map((val) => { + let sign = val < 0 ? -1 : 1; + let abs = val * sign; + if (abs > 31308e-7) { + return sign * (1.055 * abs ** (1 / 2.4) - 0.055); + } + return 12.92 * val; + }); + }, + toBase: (rgb) => { + return rgb.map((val) => { + let sign = val < 0 ? -1 : 1; + let abs = val * sign; + if (abs < 0.04045) { + return val / 12.92; + } + return sign * ((abs + 0.055) / 1.055) ** 2.4; + }); + }, + formats: { + "rgb": { + coords: coordGrammar + }, + "rgb_number": { + name: "rgb", + commas: true, + coords: coordGrammarNumber, + noAlpha: true + }, + "color": { + /* use defaults */ + }, + "rgba": { + coords: coordGrammar, + commas: true, + lastAlpha: true + }, + "rgba_number": { + name: "rgba", + commas: true, + coords: coordGrammarNumber + }, + "hex": { + type: "custom", + toGamut: true, + test: (str) => /^#([a-f0-9]{3,4}){1,2}$/i.test(str), + parse(str) { + if (str.length <= 5) { + str = str.replace(/[a-f0-9]/gi, "$&$&"); + } + let rgba = []; + str.replace(/[a-f0-9]{2}/gi, (component) => { + rgba.push(parseInt(component, 16) / 255); + }); + return { + spaceId: "srgb", + coords: rgba.slice(0, 3), + alpha: rgba.slice(3)[0] + }; + }, + serialize: (coords, alpha, { + collapse = true + // collapse to 3-4 digit hex when possible? + } = {}) => { + if (alpha < 1) { + coords.push(alpha); + } + coords = coords.map((c4) => Math.round(c4 * 255)); + let collapsible = collapse && coords.every((c4) => c4 % 17 === 0); + let hex = coords.map((c4) => { + if (collapsible) { + return (c4 / 17).toString(16); + } + return c4.toString(16).padStart(2, "0"); + }).join(""); + return "#" + hex; + } + }, + "keyword": { + type: "custom", + test: (str) => /^[a-z]+$/i.test(str), + parse(str) { + str = str.toLowerCase(); + let ret = { spaceId: "srgb", coords: null, alpha: 1 }; + if (str === "transparent") { + ret.coords = KEYWORDS.black; + ret.alpha = 0; + } else { + ret.coords = KEYWORDS[str]; + } + if (ret.coords) { + return ret; + } + } + } + } +}); +var P3 = new RGBColorSpace({ + id: "p3", + name: "P3", + base: P3Linear, + // Gamma encoding/decoding is the same as sRGB + fromBase: sRGB.fromBase, + toBase: sRGB.toBase, + formats: { + color: { + id: "display-p3" + } + } +}); +defaults.display_space = sRGB; +if (typeof CSS !== "undefined" && CSS.supports) { + for (let space of [lab, REC2020, P3]) { + let coords = space.getMinCoords(); + let color = { space, coords, alpha: 1 }; + let str = serialize(color); + if (CSS.supports("color", str)) { + defaults.display_space = space; + break; + } + } +} +function display(color, { space = defaults.display_space, ...options } = {}) { + let ret = serialize(color, options); + if (typeof CSS === "undefined" || CSS.supports("color", ret) || !defaults.display_space) { + ret = new String(ret); + ret.color = color; + } else { + let fallbackColor = to(color, space); + ret = new String(serialize(fallbackColor, options)); + ret.color = fallbackColor; + } + return ret; +} +function distance(color1, color2, space = "lab") { + space = ColorSpace.get(space); + let coords1 = space.from(color1); + let coords2 = space.from(color2); + return Math.sqrt(coords1.reduce((acc, c12, i) => { + let c22 = coords2[i]; + if (isNaN(c12) || isNaN(c22)) { + return acc; + } + return acc + (c22 - c12) ** 2; + }, 0)); +} +function equals(color1, color2) { + color1 = getColor(color1); + color2 = getColor(color2); + return color1.space === color2.space && color1.alpha === color2.alpha && color1.coords.every((c4, i) => c4 === color2.coords[i]); +} +function getLuminance(color) { + return get(color, [XYZ_D65, "y"]); +} +function setLuminance(color, value) { + set(color, [XYZ_D65, "y"], value); +} +function register$2(Color2) { + Object.defineProperty(Color2.prototype, "luminance", { + get() { + return getLuminance(this); + }, + set(value) { + setLuminance(this, value); + } + }); +} +var luminance = /* @__PURE__ */ Object.freeze({ + __proto__: null, + getLuminance, + register: register$2, + setLuminance +}); +function contrastWCAG21(color1, color2) { + color1 = getColor(color1); + color2 = getColor(color2); + let Y1 = Math.max(getLuminance(color1), 0); + let Y2 = Math.max(getLuminance(color2), 0); + if (Y2 > Y1) { + [Y1, Y2] = [Y2, Y1]; + } + return (Y1 + 0.05) / (Y2 + 0.05); +} +var normBG = 0.56; +var normTXT = 0.57; +var revTXT = 0.62; +var revBG = 0.65; +var blkThrs = 0.022; +var blkClmp = 1.414; +var loClip = 0.1; +var deltaYmin = 5e-4; +var scaleBoW = 1.14; +var loBoWoffset = 0.027; +var scaleWoB = 1.14; +function fclamp(Y) { + if (Y >= blkThrs) { + return Y; + } + return Y + (blkThrs - Y) ** blkClmp; +} +function linearize(val) { + let sign = val < 0 ? -1 : 1; + let abs = Math.abs(val); + return sign * Math.pow(abs, 2.4); +} +function contrastAPCA(background, foreground) { + foreground = getColor(foreground); + background = getColor(background); + let S; + let C; + let Sapc; + let R, G, B; + foreground = to(foreground, "srgb"); + [R, G, B] = foreground.coords; + let lumTxt = linearize(R) * 0.2126729 + linearize(G) * 0.7151522 + linearize(B) * 0.072175; + background = to(background, "srgb"); + [R, G, B] = background.coords; + let lumBg = linearize(R) * 0.2126729 + linearize(G) * 0.7151522 + linearize(B) * 0.072175; + let Ytxt = fclamp(lumTxt); + let Ybg = fclamp(lumBg); + let BoW = Ybg > Ytxt; + if (Math.abs(Ybg - Ytxt) < deltaYmin) { + C = 0; + } else { + if (BoW) { + S = Ybg ** normBG - Ytxt ** normTXT; + C = S * scaleBoW; + } else { + S = Ybg ** revBG - Ytxt ** revTXT; + C = S * scaleWoB; + } + } + if (Math.abs(C) < loClip) { + Sapc = 0; + } else if (C > 0) { + Sapc = C - loBoWoffset; + } else { + Sapc = C + loBoWoffset; + } + return Sapc * 100; +} +function contrastMichelson(color1, color2) { + color1 = getColor(color1); + color2 = getColor(color2); + let Y1 = Math.max(getLuminance(color1), 0); + let Y2 = Math.max(getLuminance(color2), 0); + if (Y2 > Y1) { + [Y1, Y2] = [Y2, Y1]; + } + let denom = Y1 + Y2; + return denom === 0 ? 0 : (Y1 - Y2) / denom; +} +var max = 5e4; +function contrastWeber(color1, color2) { + color1 = getColor(color1); + color2 = getColor(color2); + let Y1 = Math.max(getLuminance(color1), 0); + let Y2 = Math.max(getLuminance(color2), 0); + if (Y2 > Y1) { + [Y1, Y2] = [Y2, Y1]; + } + return Y2 === 0 ? max : (Y1 - Y2) / Y2; +} +function contrastLstar(color1, color2) { + color1 = getColor(color1); + color2 = getColor(color2); + let L1 = get(color1, [lab, "l"]); + let L2 = get(color2, [lab, "l"]); + return Math.abs(L1 - L2); +} +var \u03B5$1 = 216 / 24389; +var \u03B53 = 24 / 116; +var \u03BA = 24389 / 27; +var white = WHITES.D65; +var lab_d65 = new ColorSpace({ + id: "lab-d65", + name: "Lab D65", + coords: { + l: { + refRange: [0, 100], + name: "L" + }, + a: { + refRange: [-125, 125] + }, + b: { + refRange: [-125, 125] + } + }, + // Assuming XYZ is relative to D65, convert to CIE Lab + // from CIE standard, which now defines these as a rational fraction + white, + base: XYZ_D65, + // Convert D65-adapted XYZ to Lab + // CIE 15.3:2004 section 8.2.1.1 + fromBase(XYZ) { + let xyz = XYZ.map((value, i) => value / white[i]); + let f = xyz.map((value) => value > \u03B5$1 ? Math.cbrt(value) : (\u03BA * value + 16) / 116); + return [ + 116 * f[1] - 16, + // L + 500 * (f[0] - f[1]), + // a + 200 * (f[1] - f[2]) + // b + ]; + }, + // Convert Lab to D65-adapted XYZ + // Same result as CIE 15.3:2004 Appendix D although the derivation is different + // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html + toBase(Lab) { + let f = []; + f[1] = (Lab[0] + 16) / 116; + f[0] = Lab[1] / 500 + f[1]; + f[2] = f[1] - Lab[2] / 200; + let xyz = [ + f[0] > \u03B53 ? Math.pow(f[0], 3) : (116 * f[0] - 16) / \u03BA, + Lab[0] > 8 ? Math.pow((Lab[0] + 16) / 116, 3) : Lab[0] / \u03BA, + f[2] > \u03B53 ? Math.pow(f[2], 3) : (116 * f[2] - 16) / \u03BA + ]; + return xyz.map((value, i) => value * white[i]); + }, + formats: { + "lab-d65": { + coords: [" | ", " | [-1,1]", " | [-1,1]"] + } + } +}); +var phi = Math.pow(5, 0.5) * 0.5 + 0.5; +function contrastDeltaPhi(color1, color2) { + color1 = getColor(color1); + color2 = getColor(color2); + let Lstr1 = get(color1, [lab_d65, "l"]); + let Lstr2 = get(color2, [lab_d65, "l"]); + let deltaPhiStar = Math.abs(Math.pow(Lstr1, phi) - Math.pow(Lstr2, phi)); + let contrast2 = Math.pow(deltaPhiStar, 1 / phi) * Math.SQRT2 - 40; + return contrast2 < 7.5 ? 0 : contrast2; +} +var contrastMethods = /* @__PURE__ */ Object.freeze({ + __proto__: null, + contrastAPCA, + contrastDeltaPhi, + contrastLstar, + contrastMichelson, + contrastWCAG21, + contrastWeber +}); +function contrast(background, foreground, o = {}) { + if (isString(o)) { + o = { algorithm: o }; + } + let { algorithm, ...rest } = o; + if (!algorithm) { + let algorithms = Object.keys(contrastMethods).map((a2) => a2.replace(/^contrast/, "")).join(", "); + throw new TypeError(`contrast() function needs a contrast algorithm. Please specify one of: ${algorithms}`); + } + background = getColor(background); + foreground = getColor(foreground); + for (let a2 in contrastMethods) { + if ("contrast" + algorithm.toLowerCase() === a2.toLowerCase()) { + return contrastMethods[a2](background, foreground, rest); + } + } + throw new TypeError(`Unknown contrast algorithm: ${algorithm}`); +} +function uv(color) { + let [X, Y, Z] = getAll(color, XYZ_D65); + let denom = X + 15 * Y + 3 * Z; + return [4 * X / denom, 9 * Y / denom]; +} +function xy(color) { + let [X, Y, Z] = getAll(color, XYZ_D65); + let sum = X + Y + Z; + return [X / sum, Y / sum]; +} +function register$1(Color2) { + Object.defineProperty(Color2.prototype, "uv", { + get() { + return uv(this); + } + }); + Object.defineProperty(Color2.prototype, "xy", { + get() { + return xy(this); + } + }); +} +var chromaticity = /* @__PURE__ */ Object.freeze({ + __proto__: null, + register: register$1, + uv, + xy +}); +function deltaE76(color, sample) { + return distance(color, sample, "lab"); +} +var \u03C0 = Math.PI; +var d2r = \u03C0 / 180; +function deltaECMC(color, sample, { l = 2, c: c4 = 1 } = {}) { + let [L1, a1, b1] = lab.from(color); + let [, C1, H1] = lch.from(lab, [L1, a1, b1]); + let [L2, a2, b2] = lab.from(sample); + let C2 = lch.from(lab, [L2, a2, b2])[1]; + if (C1 < 0) { + C1 = 0; + } + if (C2 < 0) { + C2 = 0; + } + let \u0394L = L1 - L2; + let \u0394C = C1 - C2; + let \u0394a = a1 - a2; + let \u0394b = b1 - b2; + let H2 = \u0394a ** 2 + \u0394b ** 2 - \u0394C ** 2; + let SL = 0.511; + if (L1 >= 16) { + SL = 0.040975 * L1 / (1 + 0.01765 * L1); + } + let SC = 0.0638 * C1 / (1 + 0.0131 * C1) + 0.638; + let T; + if (Number.isNaN(H1)) { + H1 = 0; + } + if (H1 >= 164 && H1 <= 345) { + T = 0.56 + Math.abs(0.2 * Math.cos((H1 + 168) * d2r)); + } else { + T = 0.36 + Math.abs(0.4 * Math.cos((H1 + 35) * d2r)); + } + let C4 = Math.pow(C1, 4); + let F = Math.sqrt(C4 / (C4 + 1900)); + let SH = SC * (F * T + 1 - F); + let dE = (\u0394L / (l * SL)) ** 2; + dE += (\u0394C / (c4 * SC)) ** 2; + dE += H2 / SH ** 2; + return Math.sqrt(dE); +} +var Yw$1 = 203; +var XYZ_Abs_D65 = new ColorSpace({ + // Absolute CIE XYZ, with a D65 whitepoint, + // as used in most HDR colorspaces as a starting point. + // SDR spaces are converted per BT.2048 + // so that diffuse, media white is 203 cd/m² + id: "xyz-abs-d65", + name: "Absolute XYZ D65", + coords: { + x: { + refRange: [0, 9504.7], + name: "Xa" + }, + y: { + refRange: [0, 1e4], + name: "Ya" + }, + z: { + refRange: [0, 10888.3], + name: "Za" + } + }, + base: XYZ_D65, + fromBase(XYZ) { + return XYZ.map((v) => Math.max(v * Yw$1, 0)); + }, + toBase(AbsXYZ) { + return AbsXYZ.map((v) => Math.max(v / Yw$1, 0)); + } +}); +var b$1 = 1.15; +var g = 0.66; +var n$1 = 2610 / 2 ** 14; +var ninv$1 = 2 ** 14 / 2610; +var c1$2 = 3424 / 2 ** 12; +var c2$2 = 2413 / 2 ** 7; +var c3$2 = 2392 / 2 ** 7; +var p = 1.7 * 2523 / 2 ** 5; +var pinv = 2 ** 5 / (1.7 * 2523); +var d = -0.56; +var d0 = 16295499532821565e-27; +var XYZtoCone_M = [ + [0.41478972, 0.579999, 0.014648], + [-0.20151, 1.120649, 0.0531008], + [-0.0166008, 0.2648, 0.6684799] +]; +var ConetoXYZ_M = [ + [1.9242264357876067, -1.0047923125953657, 0.037651404030618], + [0.35031676209499907, 0.7264811939316552, -0.06538442294808501], + [-0.09098281098284752, -0.3127282905230739, 1.5227665613052603] +]; +var ConetoIab_M = [ + [0.5, 0.5, 0], + [3.524, -4.066708, 0.542708], + [0.199076, 1.096799, -1.295875] +]; +var IabtoCone_M = [ + [1, 0.1386050432715393, 0.05804731615611886], + [0.9999999999999999, -0.1386050432715393, -0.05804731615611886], + [0.9999999999999998, -0.09601924202631895, -0.8118918960560388] +]; +var Jzazbz = new ColorSpace({ + id: "jzazbz", + name: "Jzazbz", + coords: { + jz: { + refRange: [0, 1], + name: "Jz" + }, + az: { + refRange: [-0.5, 0.5] + }, + bz: { + refRange: [-0.5, 0.5] + } + }, + base: XYZ_Abs_D65, + fromBase(XYZ) { + let [Xa, Ya, Za] = XYZ; + let Xm = b$1 * Xa - (b$1 - 1) * Za; + let Ym = g * Ya - (g - 1) * Xa; + let LMS = multiplyMatrices(XYZtoCone_M, [Xm, Ym, Za]); + let PQLMS = LMS.map(function(val) { + let num = c1$2 + c2$2 * (val / 1e4) ** n$1; + let denom = 1 + c3$2 * (val / 1e4) ** n$1; + return (num / denom) ** p; + }); + let [Iz, az, bz] = multiplyMatrices(ConetoIab_M, PQLMS); + let Jz = (1 + d) * Iz / (1 + d * Iz) - d0; + return [Jz, az, bz]; + }, + toBase(Jzazbz2) { + let [Jz, az, bz] = Jzazbz2; + let Iz = (Jz + d0) / (1 + d - d * (Jz + d0)); + let PQLMS = multiplyMatrices(IabtoCone_M, [Iz, az, bz]); + let LMS = PQLMS.map(function(val) { + let num = c1$2 - val ** pinv; + let denom = c3$2 * val ** pinv - c2$2; + let x = 1e4 * (num / denom) ** ninv$1; + return x; + }); + let [Xm, Ym, Za] = multiplyMatrices(ConetoXYZ_M, LMS); + let Xa = (Xm + (b$1 - 1) * Za) / b$1; + let Ya = (Ym + (g - 1) * Xa) / g; + return [Xa, Ya, Za]; + }, + formats: { + // https://drafts.csswg.org/css-color-hdr/#Jzazbz + "color": {} + } +}); +var jzczhz = new ColorSpace({ + id: "jzczhz", + name: "JzCzHz", + coords: { + jz: { + refRange: [0, 1], + name: "Jz" + }, + cz: { + refRange: [0, 1], + name: "Chroma" + }, + hz: { + refRange: [0, 360], + type: "angle", + name: "Hue" + } + }, + base: Jzazbz, + fromBase(jzazbz) { + let [Jz, az, bz] = jzazbz; + let hue; + const \u03B52 = 2e-4; + if (Math.abs(az) < \u03B52 && Math.abs(bz) < \u03B52) { + hue = NaN; + } else { + hue = Math.atan2(bz, az) * 180 / Math.PI; + } + return [ + Jz, + // Jz is still Jz + Math.sqrt(az ** 2 + bz ** 2), + // Chroma + constrain(hue) + // Hue, in degrees [0 to 360) + ]; + }, + toBase(jzczhz2) { + return [ + jzczhz2[0], + // Jz is still Jz + jzczhz2[1] * Math.cos(jzczhz2[2] * Math.PI / 180), + // az + jzczhz2[1] * Math.sin(jzczhz2[2] * Math.PI / 180) + // bz + ]; + }, + formats: { + color: {} + } +}); +function deltaEJz(color, sample) { + let [Jz1, Cz1, Hz1] = jzczhz.from(color); + let [Jz2, Cz2, Hz2] = jzczhz.from(sample); + let \u0394J = Jz1 - Jz2; + let \u0394C = Cz1 - Cz2; + if (Number.isNaN(Hz1) && Number.isNaN(Hz2)) { + Hz1 = 0; + Hz2 = 0; + } else if (Number.isNaN(Hz1)) { + Hz1 = Hz2; + } else if (Number.isNaN(Hz2)) { + Hz2 = Hz1; + } + let \u0394h = Hz1 - Hz2; + let \u0394H = 2 * Math.sqrt(Cz1 * Cz2) * Math.sin(\u0394h / 2 * (Math.PI / 180)); + return Math.sqrt(\u0394J ** 2 + \u0394C ** 2 + \u0394H ** 2); +} +var c1$1 = 3424 / 4096; +var c2$1 = 2413 / 128; +var c3$1 = 2392 / 128; +var m1 = 2610 / 16384; +var m2 = 2523 / 32; +var im1 = 16384 / 2610; +var im2 = 32 / 2523; +var XYZtoLMS_M$1 = [ + [0.3592, 0.6976, -0.0358], + [-0.1922, 1.1004, 0.0755], + [7e-3, 0.0749, 0.8434] +]; +var LMStoIPT_M = [ + [2048 / 4096, 2048 / 4096, 0], + [6610 / 4096, -13613 / 4096, 7003 / 4096], + [17933 / 4096, -17390 / 4096, -543 / 4096] +]; +var IPTtoLMS_M = [ + [0.9999888965628402, 0.008605050147287059, 0.11103437159861648], + [1.00001110343716, -0.008605050147287059, -0.11103437159861648], + [1.0000320633910054, 0.56004913547279, -0.3206339100541203] +]; +var LMStoXYZ_M$1 = [ + [2.0701800566956137, -1.326456876103021, 0.20661600684785517], + [0.3649882500326575, 0.6804673628522352, -0.04542175307585323], + [-0.04959554223893211, -0.04942116118675749, 1.1879959417328034] +]; +var ictcp = new ColorSpace({ + id: "ictcp", + name: "ICTCP", + // From BT.2100-2 page 7: + // During production, signal values are expected to exceed the + // range E′ = [0.0 : 1.0]. This provides processing headroom and avoids + // signal degradation during cascaded processing. Such values of E′, + // below 0.0 or exceeding 1.0, should not be clipped during production + // and exchange. + // Values below 0.0 should not be clipped in reference displays (even + // though they represent “negative” light) to allow the black level of + // the signal (LB) to be properly set using test signals known as “PLUGE” + coords: { + i: { + refRange: [0, 1], + // Constant luminance, + name: "I" + }, + ct: { + refRange: [-0.5, 0.5], + // Full BT.2020 gamut in range [-0.5, 0.5] + name: "CT" + }, + cp: { + refRange: [-0.5, 0.5], + name: "CP" + } + }, + base: XYZ_Abs_D65, + fromBase(XYZ) { + let LMS = multiplyMatrices(XYZtoLMS_M$1, XYZ); + return LMStoICtCp(LMS); + }, + toBase(ICtCp) { + let LMS = ICtCptoLMS(ICtCp); + return multiplyMatrices(LMStoXYZ_M$1, LMS); + }, + formats: { + color: {} + } +}); +function LMStoICtCp(LMS) { + let PQLMS = LMS.map(function(val) { + let num = c1$1 + c2$1 * (val / 1e4) ** m1; + let denom = 1 + c3$1 * (val / 1e4) ** m1; + return (num / denom) ** m2; + }); + return multiplyMatrices(LMStoIPT_M, PQLMS); +} +function ICtCptoLMS(ICtCp) { + let PQLMS = multiplyMatrices(IPTtoLMS_M, ICtCp); + let LMS = PQLMS.map(function(val) { + let num = Math.max(val ** im2 - c1$1, 0); + let denom = c2$1 - c3$1 * val ** im2; + return 1e4 * (num / denom) ** im1; + }); + return LMS; +} +function deltaEITP(color, sample) { + let [I1, T1, P1] = ictcp.from(color); + let [I2, T2, P2] = ictcp.from(sample); + return 720 * Math.sqrt((I1 - I2) ** 2 + 0.25 * (T1 - T2) ** 2 + (P1 - P2) ** 2); +} +var XYZtoLMS_M = [ + [0.8190224432164319, 0.3619062562801221, -0.12887378261216414], + [0.0329836671980271, 0.9292868468965546, 0.03614466816999844], + [0.048177199566046255, 0.26423952494422764, 0.6335478258136937] +]; +var LMStoXYZ_M = [ + [1.2268798733741557, -0.5578149965554813, 0.28139105017721583], + [-0.04057576262431372, 1.1122868293970594, -0.07171106666151701], + [-0.07637294974672142, -0.4214933239627914, 1.5869240244272418] +]; +var LMStoLab_M = [ + [0.2104542553, 0.793617785, -0.0040720468], + [1.9779984951, -2.428592205, 0.4505937099], + [0.0259040371, 0.7827717662, -0.808675766] +]; +var LabtoLMS_M = [ + [0.9999999984505198, 0.39633779217376786, 0.2158037580607588], + [1.0000000088817609, -0.10556134232365635, -0.06385417477170591], + [1.0000000546724108, -0.08948418209496575, -1.2914855378640917] +]; +var OKLab = new ColorSpace({ + id: "oklab", + name: "Oklab", + coords: { + l: { + refRange: [0, 1], + name: "L" + }, + a: { + refRange: [-0.4, 0.4] + }, + b: { + refRange: [-0.4, 0.4] + } + }, + // Note that XYZ is relative to D65 + white: "D65", + base: XYZ_D65, + fromBase(XYZ) { + let LMS = multiplyMatrices(XYZtoLMS_M, XYZ); + let LMSg = LMS.map((val) => Math.cbrt(val)); + return multiplyMatrices(LMStoLab_M, LMSg); + }, + toBase(OKLab2) { + let LMSg = multiplyMatrices(LabtoLMS_M, OKLab2); + let LMS = LMSg.map((val) => val ** 3); + return multiplyMatrices(LMStoXYZ_M, LMS); + }, + formats: { + "oklab": { + coords: [" | ", " | [-1,1]", " | [-1,1]"] + } + } +}); +function deltaEOK(color, sample) { + let [L1, a1, b1] = OKLab.from(color); + let [L2, a2, b2] = OKLab.from(sample); + let \u0394L = L1 - L2; + let \u0394a = a1 - a2; + let \u0394b = b1 - b2; + return Math.sqrt(\u0394L ** 2 + \u0394a ** 2 + \u0394b ** 2); +} +var deltaEMethods = { + deltaE76, + deltaECMC, + deltaE2000, + deltaEJz, + deltaEITP, + deltaEOK +}; +function deltaE(c12, c22, o = {}) { + if (isString(o)) { + o = { method: o }; + } + let { method = defaults.deltaE, ...rest } = o; + c12 = getColor(c12); + c22 = getColor(c22); + for (let m3 in deltaEMethods) { + if ("deltae" + method.toLowerCase() === m3.toLowerCase()) { + return deltaEMethods[m3](c12, c22, rest); + } + } + throw new TypeError(`Unknown deltaE method: ${method}`); +} +function lighten(color, amount = 0.25) { + let space = ColorSpace.get("oklch", "lch"); + let lightness = [space, "l"]; + return set(color, lightness, (l) => l * (1 + amount)); +} +function darken(color, amount = 0.25) { + let space = ColorSpace.get("oklch", "lch"); + let lightness = [space, "l"]; + return set(color, lightness, (l) => l * (1 - amount)); +} +var variations = /* @__PURE__ */ Object.freeze({ + __proto__: null, + darken, + lighten +}); +function mix(c12, c22, p2 = 0.5, o = {}) { + [c12, c22] = [getColor(c12), getColor(c22)]; + if (type(p2) === "object") { + [p2, o] = [0.5, p2]; + } + let { space, outputSpace, premultiplied } = o; + let r = range(c12, c22, { space, outputSpace, premultiplied }); + return r(p2); +} +function steps(c12, c22, options = {}) { + let colorRange; + if (isRange(c12)) { + [colorRange, options] = [c12, c22]; + [c12, c22] = colorRange.rangeArgs.colors; + } + let { + maxDeltaE, + deltaEMethod, + steps: steps2 = 2, + maxSteps = 1e3, + ...rangeOptions + } = options; + if (!colorRange) { + [c12, c22] = [getColor(c12), getColor(c22)]; + colorRange = range(c12, c22, rangeOptions); + } + let totalDelta = deltaE(c12, c22); + let actualSteps = maxDeltaE > 0 ? Math.max(steps2, Math.ceil(totalDelta / maxDeltaE) + 1) : steps2; + let ret = []; + if (maxSteps !== void 0) { + actualSteps = Math.min(actualSteps, maxSteps); + } + if (actualSteps === 1) { + ret = [{ p: 0.5, color: colorRange(0.5) }]; + } else { + let step = 1 / (actualSteps - 1); + ret = Array.from({ length: actualSteps }, (_, i) => { + let p2 = i * step; + return { p: p2, color: colorRange(p2) }; + }); + } + if (maxDeltaE > 0) { + let maxDelta = ret.reduce((acc, cur, i) => { + if (i === 0) { + return 0; + } + let \u0394\u0395 = deltaE(cur.color, ret[i - 1].color, deltaEMethod); + return Math.max(acc, \u0394\u0395); + }, 0); + while (maxDelta > maxDeltaE) { + maxDelta = 0; + for (let i = 1; i < ret.length && ret.length < maxSteps; i++) { + let prev = ret[i - 1]; + let cur = ret[i]; + let p2 = (cur.p + prev.p) / 2; + let color = colorRange(p2); + maxDelta = Math.max(maxDelta, deltaE(color, prev.color), deltaE(color, cur.color)); + ret.splice(i, 0, { p: p2, color: colorRange(p2) }); + i++; + } + } + } + ret = ret.map((a2) => a2.color); + return ret; +} +function range(color1, color2, options = {}) { + if (isRange(color1)) { + let [r, options2] = [color1, color2]; + return range(...r.rangeArgs.colors, { ...r.rangeArgs.options, ...options2 }); + } + let { space, outputSpace, progression, premultiplied } = options; + color1 = getColor(color1); + color2 = getColor(color2); + color1 = clone(color1); + color2 = clone(color2); + let rangeArgs = { colors: [color1, color2], options }; + if (space) { + space = ColorSpace.get(space); + } else { + space = ColorSpace.registry[defaults.interpolationSpace] || color1.space; + } + outputSpace = outputSpace ? ColorSpace.get(outputSpace) : space; + color1 = to(color1, space); + color2 = to(color2, space); + color1 = toGamut(color1); + color2 = toGamut(color2); + if (space.coords.h && space.coords.h.type === "angle") { + let arc = options.hue = options.hue || "shorter"; + let hue = [space, "h"]; + let [\u03B81, \u03B82] = [get(color1, hue), get(color2, hue)]; + [\u03B81, \u03B82] = adjust(arc, [\u03B81, \u03B82]); + set(color1, hue, \u03B81); + set(color2, hue, \u03B82); + } + if (premultiplied) { + color1.coords = color1.coords.map((c4) => c4 * color1.alpha); + color2.coords = color2.coords.map((c4) => c4 * color2.alpha); + } + return Object.assign((p2) => { + p2 = progression ? progression(p2) : p2; + let coords = color1.coords.map((start, i) => { + let end = color2.coords[i]; + return interpolate(start, end, p2); + }); + let alpha = interpolate(color1.alpha, color2.alpha, p2); + let ret = { space, coords, alpha }; + if (premultiplied) { + ret.coords = ret.coords.map((c4) => c4 / alpha); + } + if (outputSpace !== space) { + ret = to(ret, outputSpace); + } + return ret; + }, { + rangeArgs + }); +} +function isRange(val) { + return type(val) === "function" && !!val.rangeArgs; +} +defaults.interpolationSpace = "lab"; +function register(Color2) { + Color2.defineFunction("mix", mix, { returns: "color" }); + Color2.defineFunction("range", range, { returns: "function" }); + Color2.defineFunction("steps", steps, { returns: "array" }); +} +var interpolation = /* @__PURE__ */ Object.freeze({ + __proto__: null, + isRange, + mix, + range, + register, + steps +}); +var HSL = new ColorSpace({ + id: "hsl", + name: "HSL", + coords: { + h: { + refRange: [0, 360], + type: "angle", + name: "Hue" + }, + s: { + range: [0, 100], + name: "Saturation" + }, + l: { + range: [0, 100], + name: "Lightness" + } + }, + base: sRGB, + // Adapted from https://en.wikipedia.org/wiki/HSL_and_HSV#From_RGB + fromBase: (rgb) => { + let max2 = Math.max(...rgb); + let min = Math.min(...rgb); + let [r, g2, b2] = rgb; + let [h, s, l] = [NaN, 0, (min + max2) / 2]; + let d2 = max2 - min; + if (d2 !== 0) { + s = l === 0 || l === 1 ? 0 : (max2 - l) / Math.min(l, 1 - l); + switch (max2) { + case r: + h = (g2 - b2) / d2 + (g2 < b2 ? 6 : 0); + break; + case g2: + h = (b2 - r) / d2 + 2; + break; + case b2: + h = (r - g2) / d2 + 4; + } + h = h * 60; + } + return [h, s * 100, l * 100]; + }, + // Adapted from https://en.wikipedia.org/wiki/HSL_and_HSV#HSL_to_RGB_alternative + toBase: (hsl) => { + let [h, s, l] = hsl; + h = h % 360; + if (h < 0) { + h += 360; + } + s /= 100; + l /= 100; + function f(n2) { + let k = (n2 + h / 30) % 12; + let a2 = s * Math.min(l, 1 - l); + return l - a2 * Math.max(-1, Math.min(k - 3, 9 - k, 1)); + } + return [f(0), f(8), f(4)]; + }, + formats: { + "hsl": { + toGamut: true, + coords: [" | ", "", ""] + }, + "hsla": { + coords: [" | ", "", ""], + commas: true, + lastAlpha: true + } + } +}); +var HSV = new ColorSpace({ + id: "hsv", + name: "HSV", + coords: { + h: { + refRange: [0, 360], + type: "angle", + name: "Hue" + }, + s: { + range: [0, 100], + name: "Saturation" + }, + v: { + range: [0, 100], + name: "Value" + } + }, + base: HSL, + // https://en.wikipedia.org/wiki/HSL_and_HSV#Interconversion + fromBase(hsl) { + let [h, s, l] = hsl; + s /= 100; + l /= 100; + let v = l + s * Math.min(l, 1 - l); + return [ + h, + // h is the same + v === 0 ? 0 : 200 * (1 - l / v), + // s + 100 * v + ]; + }, + // https://en.wikipedia.org/wiki/HSL_and_HSV#Interconversion + toBase(hsv) { + let [h, s, v] = hsv; + s /= 100; + v /= 100; + let l = v * (1 - s / 2); + return [ + h, + // h is the same + l === 0 || l === 1 ? 0 : (v - l) / Math.min(l, 1 - l) * 100, + l * 100 + ]; + }, + formats: { + color: { + toGamut: true + } + } +}); +var hwb = new ColorSpace({ + id: "hwb", + name: "HWB", + coords: { + h: { + refRange: [0, 360], + type: "angle", + name: "Hue" + }, + w: { + range: [0, 100], + name: "Whiteness" + }, + b: { + range: [0, 100], + name: "Blackness" + } + }, + base: HSV, + fromBase(hsv) { + let [h, s, v] = hsv; + return [h, v * (100 - s) / 100, 100 - v]; + }, + toBase(hwb2) { + let [h, w, b2] = hwb2; + w /= 100; + b2 /= 100; + let sum = w + b2; + if (sum >= 1) { + let gray = w / sum; + return [h, 0, gray * 100]; + } + let v = 1 - b2; + let s = v === 0 ? 0 : 1 - w / v; + return [h, s * 100, v * 100]; + }, + formats: { + "hwb": { + toGamut: true, + coords: [" | ", "", ""] + } + } +}); +var toXYZ_M$2 = [ + [0.5766690429101305, 0.1855582379065463, 0.1882286462349947], + [0.29734497525053605, 0.6273635662554661, 0.07529145849399788], + [0.02703136138641234, 0.07068885253582723, 0.9913375368376388] +]; +var fromXYZ_M$2 = [ + [2.0415879038107465, -0.5650069742788596, -0.34473135077832956], + [-0.9692436362808795, 1.8759675015077202, 0.04155505740717557], + [0.013444280632031142, -0.11836239223101838, 1.0151749943912054] +]; +var A98Linear = new RGBColorSpace({ + id: "a98rgb-linear", + name: "Linear Adobe\xAE 98 RGB compatible", + white: "D65", + toXYZ_M: toXYZ_M$2, + fromXYZ_M: fromXYZ_M$2 +}); +var a98rgb = new RGBColorSpace({ + id: "a98rgb", + name: "Adobe\xAE 98 RGB compatible", + base: A98Linear, + toBase: (RGB) => RGB.map((val) => Math.pow(Math.abs(val), 563 / 256) * Math.sign(val)), + fromBase: (RGB) => RGB.map((val) => Math.pow(Math.abs(val), 256 / 563) * Math.sign(val)), + formats: { + color: { + id: "a98-rgb" + } + } +}); +var toXYZ_M$1 = [ + [0.7977604896723027, 0.13518583717574031, 0.0313493495815248], + [0.2880711282292934, 0.7118432178101014, 8565396060525902e-20], + [0, 0, 0.8251046025104601] +]; +var fromXYZ_M$1 = [ + [1.3457989731028281, -0.25558010007997534, -0.05110628506753401], + [-0.5446224939028347, 1.5082327413132781, 0.02053603239147973], + [0, 0, 1.2119675456389454] +]; +var ProPhotoLinear = new RGBColorSpace({ + id: "prophoto-linear", + name: "Linear ProPhoto", + white: "D50", + base: XYZ_D50, + toXYZ_M: toXYZ_M$1, + fromXYZ_M: fromXYZ_M$1 +}); +var Et = 1 / 512; +var Et2 = 16 / 512; +var prophoto = new RGBColorSpace({ + id: "prophoto", + name: "ProPhoto", + base: ProPhotoLinear, + toBase(RGB) { + return RGB.map((v) => v < Et2 ? v / 16 : v ** 1.8); + }, + fromBase(RGB) { + return RGB.map((v) => v >= Et ? v ** (1 / 1.8) : 16 * v); + }, + formats: { + color: { + id: "prophoto-rgb" + } + } +}); +var oklch = new ColorSpace({ + id: "oklch", + name: "Oklch", + coords: { + l: { + refRange: [0, 1], + name: "Lightness" + }, + c: { + refRange: [0, 0.4], + name: "Chroma" + }, + h: { + refRange: [0, 360], + type: "angle", + name: "Hue" + } + }, + white: "D65", + base: OKLab, + fromBase(oklab) { + let [L, a2, b2] = oklab; + let h; + const \u03B52 = 2e-4; + if (Math.abs(a2) < \u03B52 && Math.abs(b2) < \u03B52) { + h = NaN; + } else { + h = Math.atan2(b2, a2) * 180 / Math.PI; + } + return [ + L, + // OKLab L is still L + Math.sqrt(a2 ** 2 + b2 ** 2), + // Chroma + constrain(h) + // Hue, in degrees [0 to 360) + ]; + }, + // Convert from polar form + toBase(oklch2) { + let [L, C, h] = oklch2; + let a2, b2; + if (isNaN(h)) { + a2 = 0; + b2 = 0; + } else { + a2 = C * Math.cos(h * Math.PI / 180); + b2 = C * Math.sin(h * Math.PI / 180); + } + return [L, a2, b2]; + }, + formats: { + "oklch": { + coords: [" | ", " | [0,1]", " | "] + } + } +}); +var Yw = 203; +var n = 2610 / 2 ** 14; +var ninv = 2 ** 14 / 2610; +var m = 2523 / 2 ** 5; +var minv = 2 ** 5 / 2523; +var c1 = 3424 / 2 ** 12; +var c2 = 2413 / 2 ** 7; +var c3 = 2392 / 2 ** 7; +var rec2100Pq = new RGBColorSpace({ + id: "rec2100pq", + name: "REC.2100-PQ", + base: REC2020Linear, + toBase(RGB) { + return RGB.map(function(val) { + let x = (Math.max(val ** minv - c1, 0) / (c2 - c3 * val ** minv)) ** ninv; + return x * 1e4 / Yw; + }); + }, + fromBase(RGB) { + return RGB.map(function(val) { + let x = Math.max(val * Yw / 1e4, 0); + let num = c1 + c2 * x ** n; + let denom = 1 + c3 * x ** n; + return (num / denom) ** m; + }); + }, + formats: { + color: { + id: "rec2100-pq" + } + } +}); +var a = 0.17883277; +var b = 0.28466892; +var c = 0.55991073; +var scale = 3.7743; +var rec2100Hlg = new RGBColorSpace({ + id: "rec2100hlg", + cssid: "rec2100-hlg", + name: "REC.2100-HLG", + referred: "scene", + base: REC2020Linear, + toBase(RGB) { + return RGB.map(function(val) { + if (val <= 0.5) { + return val ** 2 / 3 * scale; + } + return (Math.exp((val - c) / a) + b) / 12 * scale; + }); + }, + fromBase(RGB) { + return RGB.map(function(val) { + val /= scale; + if (val <= 1 / 12) { + return Math.sqrt(3 * val); + } + return a * Math.log(12 * val - b) + c; + }); + }, + formats: { + color: { + id: "rec2100-hlg" + } + } +}); +var CATs = {}; +hooks.add("chromatic-adaptation-start", (env) => { + if (env.options.method) { + env.M = adapt(env.W1, env.W2, env.options.method); + } +}); +hooks.add("chromatic-adaptation-end", (env) => { + if (!env.M) { + env.M = adapt(env.W1, env.W2, env.options.method); + } +}); +function defineCAT({ id, toCone_M, fromCone_M }) { + CATs[id] = arguments[0]; +} +function adapt(W1, W2, id = "Bradford") { + let method = CATs[id]; + let [\u03C1s, \u03B3s, \u03B2s] = multiplyMatrices(method.toCone_M, W1); + let [\u03C1d, \u03B3d, \u03B2d] = multiplyMatrices(method.toCone_M, W2); + let scale2 = [ + [\u03C1d / \u03C1s, 0, 0], + [0, \u03B3d / \u03B3s, 0], + [0, 0, \u03B2d / \u03B2s] + ]; + let scaled_cone_M = multiplyMatrices(scale2, method.toCone_M); + let adapt_M = multiplyMatrices(method.fromCone_M, scaled_cone_M); + return adapt_M; +} +defineCAT({ + id: "von Kries", + toCone_M: [ + [0.40024, 0.7076, -0.08081], + [-0.2263, 1.16532, 0.0457], + [0, 0, 0.91822] + ], + fromCone_M: [ + [1.8599364, -1.1293816, 0.2198974], + [0.3611914, 0.6388125, -64e-7], + [0, 0, 1.0890636] + ] +}); +defineCAT({ + id: "Bradford", + // Convert an array of XYZ values in the range 0.0 - 1.0 + // to cone fundamentals + toCone_M: [ + [0.8951, 0.2664, -0.1614], + [-0.7502, 1.7135, 0.0367], + [0.0389, -0.0685, 1.0296] + ], + // and back + fromCone_M: [ + [0.9869929, -0.1470543, 0.1599627], + [0.4323053, 0.5183603, 0.0492912], + [-85287e-7, 0.0400428, 0.9684867] + ] +}); +defineCAT({ + id: "CAT02", + // with complete chromatic adaptation to W2, so D = 1.0 + toCone_M: [ + [0.7328, 0.4296, -0.1624], + [-0.7036, 1.6975, 61e-4], + [3e-3, 0.0136, 0.9834] + ], + fromCone_M: [ + [1.0961238, -0.278869, 0.1827452], + [0.454369, 0.4735332, 0.0720978], + [-96276e-7, -5698e-6, 1.0153256] + ] +}); +defineCAT({ + id: "CAT16", + toCone_M: [ + [0.401288, 0.650173, -0.051461], + [-0.250268, 1.204414, 0.045854], + [-2079e-6, 0.048952, 0.953127] + ], + // the extra precision is needed to avoid roundtripping errors + fromCone_M: [ + [1.862067855087233, -1.011254630531685, 0.1491867754444518], + [0.3875265432361372, 0.6214474419314753, -0.008973985167612518], + [-0.01584149884933386, -0.03412293802851557, 1.04996443687785] + ] +}); +Object.assign(WHITES, { + // whitepoint values from ASTM E308-01 with 10nm spacing, 1931 2 degree observer + // all normalized to Y (luminance) = 1.00000 + // Illuminant A is a tungsten electric light, giving a very warm, orange light. + A: [1.0985, 1, 0.35585], + // Illuminant C was an early approximation to daylight: illuminant A with a blue filter. + C: [0.98074, 1, 1.18232], + // The daylight series of illuminants simulate natural daylight. + // The color temperature (in degrees Kelvin/100) ranges from + // cool, overcast daylight (D50) to bright, direct sunlight (D65). + D55: [0.95682, 1, 0.92149], + D75: [0.94972, 1, 1.22638], + // Equal-energy illuminant, used in two-stage CAT16 + E: [1, 1, 1], + // The F series of illuminants represent fluorescent lights + F2: [0.99186, 1, 0.67393], + F7: [0.95041, 1, 1.08747], + F11: [1.00962, 1, 0.6435] +}); +WHITES.ACES = [0.32168 / 0.33767, 1, (1 - 0.32168 - 0.33767) / 0.33767]; +var toXYZ_M = [ + [0.6624541811085053, 0.13400420645643313, 0.1561876870049078], + [0.27222871678091454, 0.6740817658111484, 0.05368951740793705], + [-0.005574649490394108, 0.004060733528982826, 1.0103391003129971] +]; +var fromXYZ_M = [ + [1.6410233796943257, -0.32480329418479, -0.23642469523761225], + [-0.6636628587229829, 1.6153315916573379, 0.016756347685530137], + [0.011721894328375376, -0.008284441996237409, 0.9883948585390215] +]; +var ACEScg = new RGBColorSpace({ + id: "acescg", + name: "ACEScg", + // ACEScg – A scene-referred, linear-light encoding of ACES Data + // https://docs.acescentral.com/specifications/acescg/ + // uses the AP1 primaries, see section 4.3.1 Color primaries + coords: { + r: { + range: [0, 65504], + name: "Red" + }, + g: { + range: [0, 65504], + name: "Green" + }, + b: { + range: [0, 65504], + name: "Blue" + } + }, + referred: "scene", + white: WHITES.ACES, + toXYZ_M, + fromXYZ_M, + formats: { + color: {} + } +}); +var \u03B5 = 2 ** -16; +var ACES_min_nonzero = -0.35828683; +var ACES_cc_max = (Math.log2(65504) + 9.72) / 17.52; +var acescc = new RGBColorSpace({ + id: "acescc", + name: "ACEScc", + // see S-2014-003 ACEScc – A Logarithmic Encoding of ACES Data + // https://docs.acescentral.com/specifications/acescc/ + // uses the AP1 primaries, see section 4.3.1 Color primaries + // Appendix A: "Very small ACES scene referred values below 7 1/4 stops + // below 18% middle gray are encoded as negative ACEScc values. + // These values should be preserved per the encoding in Section 4.4 + // so that all positive ACES values are maintained." + coords: { + r: { + range: [ACES_min_nonzero, ACES_cc_max], + name: "Red" + }, + g: { + range: [ACES_min_nonzero, ACES_cc_max], + name: "Green" + }, + b: { + range: [ACES_min_nonzero, ACES_cc_max], + name: "Blue" + } + }, + referred: "scene", + base: ACEScg, + // from section 4.4.2 Decoding Function + toBase(RGB) { + const low = (9.72 - 15) / 17.52; + return RGB.map(function(val) { + if (val <= low) { + return (2 ** (val * 17.52 - 9.72) - \u03B5) * 2; + } else if (val < ACES_cc_max) { + return 2 ** (val * 17.52 - 9.72); + } else { + return 65504; + } + }); + }, + // Non-linear encoding function from S-2014-003, section 4.4.1 Encoding Function + fromBase(RGB) { + return RGB.map(function(val) { + if (val <= 0) { + return (Math.log2(\u03B5) + 9.72) / 17.52; + } else if (val < \u03B5) { + return (Math.log2(\u03B5 + val * 0.5) + 9.72) / 17.52; + } else { + return (Math.log2(val) + 9.72) / 17.52; + } + }); + }, + // encoded media white (rgb 1,1,1) => linear [ 222.861, 222.861, 222.861 ] + // encoded media black (rgb 0,0,0) => linear [ 0.0011857, 0.0011857, 0.0011857] + formats: { + color: {} + } +}); +var spaces = /* @__PURE__ */ Object.freeze({ + __proto__: null, + A98RGB: a98rgb, + A98RGB_Linear: A98Linear, + ACEScc: acescc, + ACEScg, + HSL, + HSV, + HWB: hwb, + ICTCP: ictcp, + JzCzHz: jzczhz, + Jzazbz, + LCH: lch, + Lab: lab, + Lab_D65: lab_d65, + OKLCH: oklch, + OKLab, + P3, + P3_Linear: P3Linear, + ProPhoto: prophoto, + ProPhoto_Linear: ProPhotoLinear, + REC_2020: REC2020, + REC_2020_Linear: REC2020Linear, + REC_2100_HLG: rec2100Hlg, + REC_2100_PQ: rec2100Pq, + XYZ_ABS_D65: XYZ_Abs_D65, + XYZ_D50, + XYZ_D65, + sRGB, + sRGB_Linear: sRGBLinear +}); +var Color = class { + /** + * Creates an instance of Color. + * Signatures: + * - `new Color(stringToParse)` + * - `new Color(otherColor)` + * - `new Color({space, coords, alpha})` + * - `new Color(space, coords, alpha)` + * - `new Color(spaceId, coords, alpha)` + */ + constructor(...args) { + let color; + if (args.length === 1) { + color = getColor(args[0]); + } + let space, coords, alpha; + if (color) { + space = color.space || color.spaceId; + coords = color.coords; + alpha = color.alpha; + } else { + [space, coords, alpha] = args; + } + Object.defineProperty(this, "space", { + value: ColorSpace.get(space), + writable: false, + enumerable: true, + configurable: true + // see note in https://262.ecma-international.org/8.0/#sec-proxy-object-internal-methods-and-internal-slots-get-p-receiver + }); + this.coords = coords ? coords.slice() : [0, 0, 0]; + this.alpha = alpha < 1 ? alpha : 1; + for (let i = 0; i < this.coords.length; i++) { + if (this.coords[i] === "NaN") { + this.coords[i] = NaN; + } + } + for (let id in this.space.coords) { + Object.defineProperty(this, id, { + get: () => this.get(id), + set: (value) => this.set(id, value) + }); + } + } + get spaceId() { + return this.space.id; + } + clone() { + return new Color(this.space, this.coords, this.alpha); + } + toJSON() { + return { + spaceId: this.spaceId, + coords: this.coords, + alpha: this.alpha + }; + } + display(...args) { + let ret = display(this, ...args); + ret.color = new Color(ret.color); + return ret; + } + /** + * Get a color from the argument passed + * Basically gets us the same result as new Color(color) but doesn't clone an existing color object + */ + static get(color, ...args) { + if (color instanceof Color) { + return color; + } + return new Color(color, ...args); + } + static defineFunction(name, code, o = code) { + let { instance = true, returns } = o; + let func = function(...args) { + let ret = code(...args); + if (returns === "color") { + ret = Color.get(ret); + } else if (returns === "function") { + let f = ret; + ret = function(...args2) { + let ret2 = f(...args2); + return Color.get(ret2); + }; + Object.assign(ret, f); + } else if (returns === "array") { + ret = ret.map((c4) => Color.get(c4)); + } + return ret; + }; + if (!(name in Color)) { + Color[name] = func; + } + if (instance) { + Color.prototype[name] = function(...args) { + return func(this, ...args); + }; + } + } + static defineFunctions(o) { + for (let name in o) { + Color.defineFunction(name, o[name], o[name]); + } + } + static extend(exports) { + if (exports.register) { + exports.register(Color); + } else { + for (let name in exports) { + Color.defineFunction(name, exports[name]); + } + } + } +}; +Color.defineFunctions({ + get, + getAll, + set, + setAll, + to, + equals, + inGamut, + toGamut, + distance, + toString: serialize +}); +Object.assign(Color, { + util, + hooks, + WHITES, + Space: ColorSpace, + spaces: ColorSpace.registry, + parse, + // Global defaults one may want to configure + defaults +}); +for (let key of Object.keys(spaces)) { + ColorSpace.register(spaces[key]); +} +for (let id in ColorSpace.registry) { + addSpaceAccessors(id, ColorSpace.registry[id]); +} +hooks.add("colorspace-init-end", (space) => { + var _a; + addSpaceAccessors(space.id, space); + (_a = space.aliases) == null ? void 0 : _a.forEach((alias) => { + addSpaceAccessors(alias, space); + }); +}); +function addSpaceAccessors(id, space) { + Object.keys(space.coords); + Object.values(space.coords).map((c4) => c4.name); + let propId = id.replace(/-/g, "_"); + Object.defineProperty(Color.prototype, propId, { + // Convert coords to coords in another colorspace and return them + // Source colorspace: this.spaceId + // Target colorspace: id + get() { + let ret = this.getAll(id); + if (typeof Proxy === "undefined") { + return ret; + } + return new Proxy(ret, { + has: (obj, property) => { + try { + ColorSpace.resolveCoord([space, property]); + return true; + } catch (e) { + } + return Reflect.has(obj, property); + }, + get: (obj, property, receiver) => { + if (property && typeof property !== "symbol" && !(property in obj)) { + let { index } = ColorSpace.resolveCoord([space, property]); + if (index >= 0) { + return obj[index]; + } + } + return Reflect.get(obj, property, receiver); + }, + set: (obj, property, value, receiver) => { + if (property && typeof property !== "symbol" && !(property in obj) || property >= 0) { + let { index } = ColorSpace.resolveCoord([space, property]); + if (index >= 0) { + obj[index] = value; + this.setAll(id, obj); + return true; + } + } + return Reflect.set(obj, property, value, receiver); + } + }); + }, + // Convert coords in another colorspace to internal coords and set them + // Target colorspace: this.spaceId + // Source colorspace: id + set(coords) { + this.setAll(id, coords); + }, + configurable: true, + enumerable: true + }); +} +Color.extend(deltaEMethods); +Color.extend({ deltaE }); +Object.assign(Color, { deltaEMethods }); +Color.extend(variations); +Color.extend({ contrast }); +Color.extend(chromaticity); +Color.extend(luminance); +Color.extend(interpolation); +Color.extend(contrastMethods); + +// src/coloredClassApplyerPlugin.ts +var import_view = require("@codemirror/view"); +function coloredClassApplyer(domElement) { + const tagElements = []; + let hashEl = null; + [].forEach.call(domElement.getElementsByClassName("cm-hashtag"), (el) => { + if (el.innerText === "#") { + hashEl = el; + return; + } + tagElements.push({ + el, + hashEl, + className: `colored-tag-${el.innerText.trim().toLowerCase()}` + }); + }); + tagElements.forEach(({ el, hashEl: hashEl2, className }) => { + el.classList.forEach((cls) => { + if (cls.startsWith("colored-tag-") && cls !== className) { + el.classList.remove(cls); + hashEl2.classList.remove(cls); + } + }); + if (!el.classList.contains(className)) { + el.classList.add(className); + hashEl2.classList.add(className); + } + }); +} +var coloredClassApplyerPlugin = import_view.ViewPlugin.fromClass( + class { + constructor(view) { + coloredClassApplyer(view.dom); + } + update(update) { + coloredClassApplyer(update.view.dom); + } + } +); + +// src/ColoredTagsPluginSettingTab.ts +var import_obsidian = require("obsidian"); + +// src/defaultSettings.ts +var DEFAULT_SETTINGS = { + palette: { + seed: 0, + selected: "adaptive-soft" /* ADAPTIVE_SOFT */, + custom: "e12729-f37324-f8cc1b-72b043-007f4e" + }, + mixColors: true, + transition: true, + accessibility: { + highTextContrast: false + }, + knownTags: {}, + _version: 3 +}; + +// src/ColoredTagsPluginSettingTab.ts +var ColoredTagsPluginSettingTab = class extends import_obsidian.PluginSettingTab { + constructor(app, plugin) { + super(app, plugin); + this.showExperimental = false; + this.showAccessibility = false; + this.plugin = plugin; + } + renderPalette(paletteEl) { + paletteEl.empty(); + let palette = this.plugin.palettes.light; + if (window.matchMedia("(prefers-color-scheme: dark)").matches) { + palette = this.plugin.palettes.dark; + } + palette.forEach((paletteColor, index) => { + const firstElementStyles = "border-radius: var(--radius-m) 0 0 var(--radius-m)"; + const lastElementStyles = "border-radius: 0 var(--radius-m) var(--radius-m) 0"; + const styles = [ + index === 0 && firstElementStyles, + "flex: 1", + "height: 2em", + `background-color: ${paletteColor}`, + index === palette.length - 1 && lastElementStyles + ]; + paletteEl.createEl("div", { + attr: { style: styles.filter(Boolean).join(";") } + }); + }); + } + renderTags(containerEl) { + const tagsObject = this.app.metadataCache.getTags(); + const tagsArray = Object.keys(tagsObject); + if (!tagsArray.length) { + return; + } + const tagEl = containerEl.createEl("div", { + cls: "tagsExample", + attr: { + style: `display: flex; gap: 0.5em; align-items: center; justify-content: space-between; flex-wrap: wrap; margin: 1em 0 2em;` + } + }); + tagsArray.sort((a2, b2) => { + return tagsObject[b2] - tagsObject[a2]; + }); + const mostPopularTags = tagsArray.splice(0, 2); + const mostPopularNestedTags = Object.values( + tagsArray.reduce((acc, tag) => { + const nestingLevel = tag.split("/").length; + if (!acc[nestingLevel]) { + acc[nestingLevel] = tag; + } + return acc; + }, {}) + ); + [...mostPopularTags, ...mostPopularNestedTags].forEach((tag) => { + const link = tagEl.createEl("a", { attr: { href: tag } }); + link.classList.add("tag"); + link.innerText = tag; + }); + } + display() { + const { containerEl } = this; + containerEl.empty(); + this.renderTags(containerEl); + const paletteEl = containerEl.createEl("div", { + cls: "palette", + attr: { style: `display: flex; align-items: stretch` } + }); + this.renderPalette(paletteEl); + new import_obsidian.Setting(containerEl).setHeading().setName("Palette").setDesc("Select palette").addDropdown( + (dropdown) => dropdown.addOptions({ + ["adaptive-soft" /* ADAPTIVE_SOFT */]: "\u{1F338} Adaptive soft", + ["adaptive-bright" /* ADAPTIVE_BRIGHT */]: "\u{1F33A} Adaptive bright", + ["custom" /* CUSTOM */]: "Custom" + }).setValue(String(this.plugin.settings.palette.selected)).onChange(async (value) => { + this.plugin.settings.palette.selected = value; + await this.plugin.saveSettings(); + this.display(); + }) + ); + if (this.plugin.settings.palette.selected === "custom") { + const customPaletteField = new import_obsidian.Setting(containerEl).setName("Custom palette").setDesc("").addText((text) => { + text.inputEl.style.minWidth = "100%"; + text.setValue( + this.plugin.settings.palette.custom + ).setPlaceholder("Paste palette"); + text.onChange(async (value) => { + if (/^([A-Fa-f0-9]{6}(-|$))+$/i.test(value)) { + this.plugin.settings.palette.custom = value; + await this.plugin.saveSettings(); + this.renderPalette(paletteEl); + } + }); + }); + customPaletteField.descEl.innerHTML = ` + The format is XXXXXX-XXXXXX-XXXXXX for each RGB color.
+ You can share the best color palettes or get one from the community. + `.trim(); + } + new import_obsidian.Setting(containerEl).setName("Palette shift").setDesc( + "If the colors of some tags don't fit, you can shift the palette." + ).addSlider( + (slider) => slider.setLimits(0, this.plugin.palettes.light.length - 1, 1).setValue(this.plugin.settings.palette.seed).onChange(async (value) => { + slider.showTooltip(); + this.plugin.settings.palette.seed = value; + await this.plugin.saveSettings(); + this.renderPalette(paletteEl); + }) + ); + new import_obsidian.Setting(containerEl).setHeading().setName("\u{1F9BE} Accessibility").setDesc("Show accessibility options").addToggle( + (toggle) => toggle.setValue(this.showAccessibility).onChange(async (value) => { + this.showAccessibility = value; + this.display(); + }) + ); + if (this.showAccessibility) { + new import_obsidian.Setting(containerEl).setName("High text contrast").setDesc("Use only white and black colors for texts").addToggle( + (toggle) => toggle.setValue( + this.plugin.settings.accessibility.highTextContrast + ).onChange(async (value) => { + this.plugin.settings.accessibility.highTextContrast = value; + await this.plugin.saveSettings(); + this.display(); + }) + ); + } + new import_obsidian.Setting(containerEl).setHeading().setName("\u{1F9EA} Experimental").setDesc( + "Dangerous actions or insanely unstable options that could be changed or removed in any time" + ).addToggle( + (toggle) => toggle.setValue(this.showExperimental).onChange(async (value) => { + this.showExperimental = value; + this.display(); + }) + ); + if (this.showExperimental) { + new import_obsidian.Setting(containerEl).setName("Mix colors").setDesc("It helps to make text readable").addToggle( + (toggle) => toggle.setValue(this.plugin.settings.mixColors).onChange(async (value) => { + this.plugin.settings.mixColors = value; + await this.plugin.saveSettings(); + this.display(); + }) + ); + new import_obsidian.Setting(containerEl).setName("Gradient transition").addToggle( + (toggle) => toggle.setValue(this.plugin.settings.transition).onChange(async (value) => { + this.plugin.settings.transition = value; + await this.plugin.saveSettings(); + this.display(); + }) + ); + new import_obsidian.Setting(containerEl).setName("Reset config").setDesc( + "\u{1F6A8} All colors of all tags will be recalculated as if it was the first launch of the plugin. Requires restart of Obsidian." + ).addButton( + (button) => button.setButtonText("Reset").setClass("mod-warning").onClick(async () => { + new import_obsidian.Notice( + `\u2705 Reset is done +Please restart Obsidian`, + 1e4 + ); + button.setDisabled(true); + button.buttonEl.setAttribute("disabled", "true"); + button.buttonEl.classList.remove("mod-warning"); + this.plugin.settings = Object.assign( + {}, + DEFAULT_SETTINGS + ); + await this.plugin.saveData(this.plugin.settings); + }) + ); + } + } +}; + +// src/main.ts +var ColoredTagsPlugin = class extends import_obsidian2.Plugin { + constructor() { + super(...arguments); + this.renderedTagsSet = /* @__PURE__ */ new Set(); + this.palettes = { + light: [], + dark: [] + }; + } + async onload() { + await this.loadSettings(); + this.tagsMap = new Map(Object.entries(this.settings.knownTags)); + this.app.workspace.onLayoutReady(async () => { + await this.saveKnownTags(); + this.reload(); + window.setTimeout(() => { + this.checkUpdates(); + }, 5e3); + this.registerEvent( + this.app.workspace.on( + "editor-change", + (0, import_obsidian2.debounce)( + async () => { + await this.saveKnownTags(); + this.update(); + }, + 3e3, + true + ) + ) + ); + this.registerEvent( + this.app.workspace.on( + "active-leaf-change", + (0, import_obsidian2.debounce)( + async () => { + await this.saveKnownTags(); + this.update(); + }, + 300, + true + ) + ) + ); + this.addSettingTab(new ColoredTagsPluginSettingTab(this.app, this)); + this.registerEditorExtension(coloredClassApplyerPlugin); + }); + } + // O(n^2) + // Need to be optimized + async saveKnownTags() { + let isNeedToSave = false; + const combinedSet = new Set(this.tagsMap.keys()); + this.getTagsFromApp().forEach((tag) => { + combinedSet.add(tag); + }); + const combinedTags = Array.from(combinedSet); + combinedTags.forEach((tag, index) => { + const chunks = tag.split("/"); + let combinedTag = ""; + chunks.forEach((chunk, chunkIndex) => { + const key = [combinedTag, chunk].filter(Boolean).join("/"); + if (!this.tagsMap.has(key)) { + const siblings = combinedTags.filter((keyd) => { + return keyd.split("/").length === chunkIndex + 1 && keyd.startsWith(combinedTag); + }); + const maxValue = siblings.reduce((acc, sibling) => { + return Math.max(acc, this.tagsMap.get(sibling) || 0); + }, 0); + this.tagsMap.set(key, maxValue + 1); + isNeedToSave = true; + } + combinedTag = key; + }); + }); + if (isNeedToSave) { + this.settings.knownTags = Object.fromEntries( + this.tagsMap.entries() + ); + await this.saveData(this.settings); + } + } + getTagsFromApp() { + const tagsArray = Object.keys(this.app.metadataCache.getTags()); + return tagsArray.map((tag) => { + return tag.replace(/#/g, ""); + }).filter((tag) => !tag.match(/\/$/)).filter((x) => x.length); + } + update() { + const tags = this.tagsMap; + tags.forEach((order, tagName) => { + if (!this.renderedTagsSet.has(tagName)) { + this.renderedTagsSet.add(tagName); + this.colorizeTag(tagName); + } + }); + } + async checkUpdates() { + try { + const { json: response } = await (0, import_obsidian2.requestUrl)({ + url: "https://api.github.com/repos/pfrankov/obsidian-colored-tags/releases/latest", + method: "GET", + headers: { + "Content-Type": "application/json" + }, + contentType: "application/json" + }); + if (response.tag_name !== this.manifest.version) { + new import_obsidian2.Notice(`\u2B06\uFE0F Colored Tags: a new version is available`); + } + } catch (error) { + console.error(error); + } + } + reload() { + this.onunload(); + this.generatePalettes(); + this.update(); + this.updatingInterval = window.setInterval( + this.checkUpdates.bind(this), + 108e5 + ); + } + async saveSettings() { + await this.saveData(this.settings); + this.reload(); + } + getColors(input, palette, isMixing, isTransition, highTextContrast) { + const chunks = input.split("/"); + let combinedTag = ""; + const gradientStops = []; + let backgroundColor; + let lastColor = ""; + chunks.forEach((chunk) => { + const key = [combinedTag, chunk].filter(Boolean).join("/"); + const order = this.tagsMap.get(key) || 1; + const filteredPalette = palette.filter( + (colorString) => colorString !== lastColor + ); + const colorFromPalette = filteredPalette[(order - 1) % filteredPalette.length]; + lastColor = colorFromPalette; + let newColor; + if (backgroundColor) { + if (isMixing) { + const mixingLevel = isTransition ? 0.5 : 0.4; + newColor = backgroundColor.mix( + colorFromPalette, + mixingLevel, + { space: "lch" } + ); + if (newColor.deltaE2000(backgroundColor) < 10) { + newColor = backgroundColor.mix( + colorFromPalette, + mixingLevel + 0.1, + { space: "lch" } + ); + } + } else { + newColor = new Color(colorFromPalette).to("lch"); + } + } + if (!backgroundColor) { + backgroundColor = new Color(colorFromPalette).to("lch"); + combinedTag = key; + newColor = backgroundColor; + } + gradientStops.push({ + color: newColor.toString({ format: "lch" }), + chunk + }); + }); + const background = backgroundColor.toString({ format: "lch" }); + const defaultGap = isTransition ? 50 : 0; + const gap = defaultGap / gradientStops.length * 2; + const sumOfGaps = gap * (gradientStops.length - 1); + const elementSize = (100 - sumOfGaps) / gradientStops.length; + const linearGradient = gradientStops.map((item, index) => { + const start = index * (elementSize + gap); + const end = start + elementSize; + return `${item.color} ${start}% max(2em, ${end}%)`; + }); + let color; + if (highTextContrast) { + const whiteColor = new Color("white"); + const blackColor = new Color("black"); + const onWhite = Math.abs( + backgroundColor.contrast(whiteColor, "APCA") + ); + const onBlack = Math.abs( + backgroundColor.contrast(blackColor, "APCA") + ); + color = onWhite > onBlack ? whiteColor : blackColor; + } else { + color = darkenColorForContrast(backgroundColor); + } + return { background, color, linearGradient }; + } + colorizeTag(tagName) { + tagName = tagName.replace(/#/g, ""); + const tagHref = "#" + tagName.replace(/\//g, "\\/"); + const tagFlat = tagName.replace(/[^0-9a-z-]/gi, ""); + const { + background: backgroundLight, + color: colorLight, + linearGradient: linearGradientLight + } = this.getColors( + tagName, + this.palettes.light, + this.settings.mixColors, + this.settings.transition, + this.settings.accessibility.highTextContrast + ); + const { + background: backgroundDark, + color: colorDark, + linearGradient: linearGradientDark + } = this.getColors( + tagName, + this.palettes.dark, + this.settings.mixColors, + this.settings.transition, + this.settings.accessibility.highTextContrast + ); + const selectors = [ + `a.tag[href="${tagHref}"]`, + `.cm-s-obsidian .cm-line span.cm-hashtag.colored-tag-${tagName.toLowerCase().replace(/\//g, "\\/")}` + ]; + if (tagFlat) { + selectors.push( + `.cm-s-obsidian .cm-line span.cm-tag-${tagFlat.toLowerCase()}.cm-hashtag` + ); + selectors.push( + `.cm-s-obsidian .cm-line span.cm-tag-${tagFlat}.cm-hashtag` + ); + } + const lightThemeSelectors = selectors.map( + (selector) => "body " + selector + ); + const darkThemeSelectors = selectors.map( + (selector) => "body.theme-dark " + selector + ); + const linearGradientRotation = "108deg"; + appendCSS(` + ${lightThemeSelectors.join(", ")} { + background-color: ${backgroundLight}; + color: ${colorLight}; + background-image: linear-gradient(${linearGradientRotation}, ${linearGradientLight.join( + ", " + )}); + } + ${darkThemeSelectors.join(", ")} { + background-color: ${backgroundDark}; + color: ${colorDark}; + background-image: linear-gradient(${linearGradientRotation}, ${linearGradientDark.join( + ", " + )}); + } + `); + } + generatePalettes() { + if (this.settings.palette.selected === "custom" /* CUSTOM */) { + const paletteString = this.settings.palette.custom; + const palette = paletteString.split("-").filter(Boolean).map((str) => `#${str}`); + if (palette) { + this.palettes = { + light: processColorPalette({ + isDarkTheme: false, + palette, + seed: this.settings.palette.seed + }), + dark: processColorPalette({ + isDarkTheme: true, + palette, + seed: this.settings.palette.seed + }) + }; + return; + } + } + let baseChroma = 16; + let baseLightness = 87; + let offset = 35; + if (this.settings.palette.selected === "adaptive-bright" /* ADAPTIVE_BRIGHT */) { + baseChroma = 85; + baseLightness = 75; + } + const commonPaletteConfig = { + paletteSize: 8, + seed: this.settings.palette.seed, + isShuffling: true, + baseChroma, + baseLightness + }; + this.palettes = { + light: generateAdaptiveColorPalette({ + isDarkTheme: false, + ...commonPaletteConfig, + constantOffset: offset + }), + dark: generateAdaptiveColorPalette({ + isDarkTheme: true, + ...commonPaletteConfig, + constantOffset: offset + }) + }; + } + async loadSettings() { + const loadedData = await this.loadData(); + let needToSave = false; + if (loadedData && loadedData._version < 2) { + needToSave = true; + loadedData.palette = 16; + loadedData._version = 2; + } + if (loadedData && loadedData._version < 3) { + needToSave = true; + delete loadedData.palette; + loadedData.palette = { + ...DEFAULT_SETTINGS.palette, + seed: loadedData.seed + }; + if (loadedData.chroma > 16 || loadedData.lightness > 87) { + loadedData.palette.selected = "adaptive-bright" /* ADAPTIVE_BRIGHT */; + } + delete loadedData.chroma; + delete loadedData.lightness; + delete loadedData.seed; + loadedData._version = 3; + } + this.settings = Object.assign({}, DEFAULT_SETTINGS, loadedData); + if (needToSave) { + await this.saveData(this.settings); + } + } + onunload() { + this.renderedTagsSet.clear(); + removeCSS(); + window.clearInterval(this.updatingInterval); + } +}; +var darkenMemoization = /* @__PURE__ */ new Map(); +function darkenColorForContrast(baseColor) { + const CONTRAST = 4.5; + const memoizationKey = `${baseColor}`; + if (darkenMemoization.has(memoizationKey)) { + return darkenMemoization.get(memoizationKey); + } + const colorLight = new Color(baseColor).to("lch"); + const colorDark = new Color(baseColor).to("lch"); + colorLight.c += 3; + colorDark.c += 20; + if (colorLight.c > 100) { + colorLight.c = 100; + } + if (colorDark.c > 100) { + colorDark.c = 100; + } + let result = "#fff"; + for (let i = 0; i < 100; i++) { + if (baseColor.contrastAPCA(colorLight) <= -60 && colorLight.contrastWCAG21(baseColor) >= CONTRAST) { + result = colorLight.toString(); + break; + } + if (baseColor.contrastAPCA(colorDark) >= 60 && colorDark.contrastWCAG21(baseColor) >= CONTRAST) { + result = colorDark.toString(); + break; + } + colorLight.l++; + colorDark.l--; + } + darkenMemoization.set(memoizationKey, result); + return result; +} +function generateAdaptiveColorPalette({ + isDarkTheme, + paletteSize, + baseChroma, + baseLightness, + constantOffset, + isShuffling, + seed +}) { + const hueIncrement = 360 / paletteSize; + const availableColors = []; + for (let i = 0; i < paletteSize; i++) { + const hue = i * hueIncrement + constantOffset; + let chroma = baseChroma; + let lightness = baseLightness; + if (isDarkTheme) { + chroma = Math.min(Math.round(baseChroma * 1.8), 100); + lightness = Math.min(Math.round(baseLightness / 2.5), 100); + } + const lchColor = new Color("lch", [ + lightness, + chroma, + hue % 360 + ]).toString(); + availableColors.push(lchColor); + } + if (!isShuffling) { + return availableColors; + } + const result = []; + let next = 0; + const len = availableColors.length; + while (result.length < len) { + result.push(availableColors[next]); + availableColors.splice(next, 1); + next = Math.round(next + availableColors.length / 3) % availableColors.length; + } + const cut = result.splice(-seed, seed); + result.splice(0, 0, ...cut); + return result; +} +function processColorPalette({ + isDarkTheme, + palette, + seed +}) { + const availableColors = []; + for (const item of palette) { + availableColors.push(new Color(item).to("lch").toString()); + } + const result = availableColors; + const cut = result.splice(-seed, seed); + result.splice(0, 0, ...cut); + return result; +} +var appendingCSSBuffer = []; +function appendCSS(css) { + appendingCSSBuffer.push(css); + if (appendingCSSBuffer.length > 1) { + return; + } + Promise.resolve().then(() => { + let styleEl = document.head.querySelector("[colored-tags-style]"); + if (!styleEl) { + styleEl = document.head.createEl("style", { + type: "text/css", + attr: { "colored-tags-style": "" } + }); + } + styleEl.appendText(appendingCSSBuffer.join("\n")); + appendingCSSBuffer = []; + }); +} +function removeCSS() { + document.head.querySelectorAll("[colored-tags-style]").forEach((el) => { + el.remove(); + }); +} + +/* nosourcemap */ \ No newline at end of file diff --git a/.obsidian/plugins/colored-tags/manifest.json b/.obsidian/plugins/colored-tags/manifest.json new file mode 100644 index 00000000..1d2c7014 --- /dev/null +++ b/.obsidian/plugins/colored-tags/manifest.json @@ -0,0 +1,10 @@ +{ + "id": "colored-tags", + "name": "Colored Tags", + "version": "5.0.1", + "minAppVersion": "0.15.0", + "description": "Colorizes tags in different colors. Colors of nested tags are mixed with the root tag to improve readability. Text color contrast is automatically matched to comply with AA level of WCAG 2.1.", + "author": "Pavel Frankov", + "authorUrl": "https://github.com/pfrankov", + "isDesktopOnly": false +} \ No newline at end of file diff --git a/.obsidian/plugins/recent-files-obsidian/data.json b/.obsidian/plugins/recent-files-obsidian/data.json index cb90772a..703836a4 100644 --- a/.obsidian/plugins/recent-files-obsidian/data.json +++ b/.obsidian/plugins/recent-files-obsidian/data.json @@ -1,5 +1,105 @@ { "recentFiles": [ + { + "basename": "使用Obsidian打造个人图书馆!", + "path": "10-WebClipper/电子书/使用Obsidian打造个人图书馆!.md" + }, + { + "basename": "Obsidian 知识体系搭建:入门篇 (一)_牛客网", + "path": "10-WebClipper/知识体系/Obsidian 知识体系搭建:入门篇 (一)_牛客网.md" + }, + { + "basename": "zotero-obsidian联动配置", + "path": "08-Inbox/99-黑曜石玩家指南/1-obsidian入门/zotero-obsidian联动配置.md" + }, + { + "basename": "obsidian撰写草稿", + "path": "08-Inbox/99-黑曜石玩家指南/1-obsidian入门/obsidian撰写草稿.md" + }, + { + "basename": "在obsidian中写幻灯片", + "path": "08-Inbox/99-黑曜石玩家指南/1-obsidian入门/在obsidian中写幻灯片.md" + }, + { + "basename": "使用手机撰写日志", + "path": "08-Inbox/99-黑曜石玩家指南/1-obsidian入门/使用手机撰写日志.md" + }, + { + "basename": "软件下载安装", + "path": "08-Inbox/99-黑曜石玩家指南/1-obsidian入门/软件下载安装.md" + }, + { + "basename": "每周定期汇总小结", + "path": "08-Inbox/99-黑曜石玩家指南/1-obsidian入门/每周定期汇总小结.md" + }, + { + "basename": "开箱写日志", + "path": "08-Inbox/99-黑曜石玩家指南/1-obsidian入门/开箱写日志.md" + }, + { + "basename": "本章小结-恭喜入门obsidian", + "path": "08-Inbox/99-黑曜石玩家指南/1-obsidian入门/本章小结-恭喜入门obsidian.md" + }, + { + "basename": "入库文献泛读", + "path": "08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/入库文献泛读.md" + }, + { + "basename": "主题阅读与比较阅读", + "path": "08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/主题阅读与比较阅读.md" + }, + { + "basename": "重要综述如何阅读", + "path": "08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/重要综述如何阅读.md" + }, + { + "basename": "解析文章骨架", + "path": "08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/解析文章骨架.md" + }, + { + "basename": "进一步阅读原文", + "path": "08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/进一步阅读原文.md" + }, + { + "basename": "阶段性文献阅读小结", + "path": "08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/阶段性文献阅读小结.md" + }, + { + "basename": "跟踪领域内大牛", + "path": "08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/跟踪领域内大牛.md" + }, + { + "basename": "当期文献速览", + "path": "08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/当期文献速览.md" + }, + { + "basename": "本章小结-恭喜习得内功", + "path": "08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/本章小结-恭喜习得内功.md" + }, + { + "basename": "python代码说明与调试方法", + "path": "08-Inbox/99-黑曜石玩家指南/4-obsidian附录/python代码说明与调试方法.md" + }, + { + "basename": "obsidian模板库更新方法", + "path": "08-Inbox/99-黑曜石玩家指南/4-obsidian附录/obsidian模板库更新方法.md" + }, + { + "basename": "obsidian快捷键", + "path": "08-Inbox/99-黑曜石玩家指南/4-obsidian附录/obsidian快捷键.md" + }, + { + "basename": "obsidian第三方插件列表", + "path": "08-Inbox/99-黑曜石玩家指南/4-obsidian附录/obsidian第三方插件列表.md" + }, + { + "basename": "结束语", + "path": "08-Inbox/99-黑曜石玩家指南/4-obsidian附录/结束语.md" + }, + { + "basename": "让笔记流动起来——Obsidian重塑知识体系 - 少数派", + "path": "10-WebClipper/知识体系/让笔记流动起来——Obsidian重塑知识体系 - 少数派.md" + }, { "basename": "(74 封私信) Obsidian知识管理体系搭建实战指南 - 知乎", "path": "10-WebClipper/知识体系/(74 封私信) Obsidian知识管理体系搭建实战指南 - 知乎.md" @@ -28,22 +128,10 @@ "basename": "2025-07-18", "path": "01-工作日记/2025-07-18.md" }, - { - "basename": "使用手机撰写日志", - "path": "08-Inbox/99-黑曜石玩家指南/1-obsidian入门/使用手机撰写日志.md" - }, { "basename": "第29周总结", "path": "50-Memos/2025/weekly/第29周总结.md" }, - { - "basename": "本章小结-恭喜习得内功", - "path": "08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/本章小结-恭喜习得内功.md" - }, - { - "basename": "当期文献速览", - "path": "08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/当期文献速览.md" - }, { "basename": "第28周总结", "path": "50-Memos/2025/weekly/第28周总结.md" @@ -111,30 +199,6 @@ { "basename": "使用Obsidian打造个人图书馆! -转自知乎", "path": "04-博客发布/041-人文历史/使用Obsidian打造个人图书馆! -转自知乎.md" - }, - { - "basename": "微信机器人", - "path": "03-学习笔记/微信机器人.md" - }, - { - "basename": "微信公众号RSS", - "path": "03-学习笔记/微信公众号RSS.md" - }, - { - "basename": "OB插件", - "path": "03-学习笔记/OB插件.md" - }, - { - "basename": "Memos", - "path": "03-学习笔记/Memos.md" - }, - { - "basename": "kyhNGvh5iFc9eYXy2YuYWx_FDF8C04E-22D3-4D4C-9ED0-F52A326B9801", - "path": "50-Memos/2025/07/resources/kyhNGvh5iFc9eYXy2YuYWx_FDF8C04E-22D3-4D4C-9ED0-F52A326B9801.jpg" - }, - { - "basename": "6cb2VU3rkihszQLFDerqA2_2_20250712120414", - "path": "50-Memos/2025/07/resources/6cb2VU3rkihszQLFDerqA2_2_20250712120414.png" } ], "omittedPaths": [], diff --git a/.obsidian/workspace.json b/.obsidian/workspace.json index 9acf97e0..cca37233 100644 --- a/.obsidian/workspace.json +++ b/.obsidian/workspace.json @@ -23,16 +23,15 @@ "state": { "type": "markdown", "state": { - "file": "10-WebClipper/知识体系/(74 封私信) Obsidian知识管理体系搭建实战指南 - 知乎.md", + "file": "10-WebClipper/电子书/使用Obsidian打造个人图书馆!.md", "mode": "source", "source": false }, "icon": "lucide-file", - "title": "(74 封私信) Obsidian知识管理体系搭建实战指南 - 知乎" + "title": "使用Obsidian打造个人图书馆!" } } - ], - "currentTab": 1 + ] } ], "direction": "vertical" @@ -189,13 +188,13 @@ "state": { "type": "outline", "state": { - "file": "10-WebClipper/知识体系/(74 封私信) Obsidian知识管理体系搭建实战指南 - 知乎.md", + "file": "10-WebClipper/电子书/使用Obsidian打造个人图书馆!.md", "followCursor": true, "showSearch": false, "searchQuery": "" }, "icon": "lucide-list", - "title": "(74 封私信) Obsidian知识管理体系搭建实战指南 - 知乎 的大纲" + "title": "使用Obsidian打造个人图书馆! 的大纲" } }, { @@ -204,10 +203,10 @@ "state": { "type": "file-properties", "state": { - "file": "10-WebClipper/知识体系/(74 封私信) Obsidian知识管理体系搭建实战指南 - 知乎.md" + "file": "10-WebClipper/电子书/使用Obsidian打造个人图书馆!.md" }, "icon": "lucide-info", - "title": "(74 封私信) Obsidian知识管理体系搭建实战指南 - 知乎的笔记属性" + "title": "使用Obsidian打造个人图书馆!的笔记属性" } }, { @@ -231,7 +230,7 @@ } } ], - "currentTab": 4 + "currentTab": 3 }, { "id": "ad86bdfc0cc9f06b", @@ -320,37 +319,38 @@ "hidden-folder-obsidian:隐藏文件夹": false } }, - "active": "5b20dc67eb1dc6ae", + "active": "1709992a9efac806", "lastOpenFiles": [ - "40-Podcast/podnotes/Special English-World Humanoid Robot Games reveal new competition events.mp3", - "40-Podcast/podnotes/Special English-World Humanoid Robot Games reveal new competition events.md", - "10-WebClipper/Docker/如何在Docker中安全进入未启动的容器进行调试和配置 - 云原生实践.md", - "10-WebClipper/Docker/docker 未运行的容器如何进入_mob64ca12e41d46的技术博客_51CTO博客.md", - "03-学习笔记/Calibre电子书平台.md", - "01-工作日记/2025-07-18.md", + "10-WebClipper/知识体系/Obsidian 知识体系搭建:入门篇 (一)_牛客网.md", + "08-Inbox/99-黑曜石玩家指南/1-obsidian入门/zotero-obsidian联动配置.md", + "08-Inbox/99-黑曜石玩家指南/1-obsidian入门/obsidian撰写草稿.md", + "08-Inbox/99-黑曜石玩家指南/1-obsidian入门/在obsidian中写幻灯片.md", "08-Inbox/99-黑曜石玩家指南/1-obsidian入门/使用手机撰写日志.md", - "50-Memos/2025/weekly/第29周总结.md", - "08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/本章小结-恭喜习得内功.md", + "08-Inbox/99-黑曜石玩家指南/1-obsidian入门/软件下载安装.md", + "08-Inbox/99-黑曜石玩家指南/1-obsidian入门/每周定期汇总小结.md", + "08-Inbox/99-黑曜石玩家指南/1-obsidian入门/开箱写日志.md", + "08-Inbox/99-黑曜石玩家指南/1-obsidian入门/本章小结-恭喜入门obsidian.md", + "08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/入库文献泛读.md", + "08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/主题阅读与比较阅读.md", + "08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/重要综述如何阅读.md", + "08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/解析文章骨架.md", + "08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/进一步阅读原文.md", + "08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/阶段性文献阅读小结.md", + "08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/跟踪领域内大牛.md", "08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/当期文献速览.md", + "08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/本章小结-恭喜习得内功.md", + "08-Inbox/99-黑曜石玩家指南/4-obsidian附录/python代码说明与调试方法.md", + "08-Inbox/99-黑曜石玩家指南/4-obsidian附录/obsidian模板库更新方法.md", + "08-Inbox/99-黑曜石玩家指南/4-obsidian附录/obsidian快捷键.md", + "08-Inbox/99-黑曜石玩家指南/4-obsidian附录/obsidian第三方插件列表.md", + "08-Inbox/99-黑曜石玩家指南/4-obsidian附录/结束语.md", + "10-WebClipper/知识体系/让笔记流动起来——Obsidian重塑知识体系 - 少数派.md", + "10-WebClipper/电子书/使用Obsidian打造个人图书馆!.md", + "10-WebClipper/知识体系/(74 封私信) Obsidian知识管理体系搭建实战指南 - 知乎.md", + "40-Podcast/podnotes/Special English-World Humanoid Robot Games reveal new competition events.mp3", "60-Imports/62-DevonThink", "60-Imports/61-CubeX", - "50-Memos/2025/weekly/第28周总结.md", - "04-博客发布/043-Bridge/技惊四座的Deep Finesse打法.md", - "01-工作日记/2025-07-17.md", - "10-WebClipper/开源/AList的开源替代:OpenList.md", - "README.md", - "听写.md", - "20-我的收藏夹/21-浏览器收藏/电子书/电子书制作/(5 封私信 44 条消息) 制作和编辑 ePub (电子书)有哪些工具值得推荐? - 知乎.md", - "20-我的收藏夹/21-浏览器收藏/开发网站/App打包/(5 封私信 82 条消息) webapp,混合app,套壳app有什么区别? - 知乎.md", - "20-我的收藏夹/21-浏览器收藏/开发网站/20230709/(5 封私信 48 条消息) 有哪些强大的桌面应用是基于Electron开发的? - 知乎 (1).md", - "20-我的收藏夹/21-浏览器收藏/游戏网站/(1)百度CSGO吧导航——2014-3-15更新_cs起源吧戴维_新浪博客.md", - "20-我的收藏夹/21-浏览器收藏/开发网站/webplayer/(1) 视频播放不能跳转到vlc · Issue 5029 · alist-orgalist.md", - "20-我的收藏夹/21-浏览器收藏/硬/软件评测/记账软件/“随手记”还是“神象云”?总有一款记账工具适合你 - 知乎.md", - "08-Inbox/99-黑曜石玩家指南/99-黑曜石玩家指南.md", - "08-Inbox/2025-07-04.md", "08-Inbox/assets/68691ee74ca1b.png", - "08-Inbox/mindmapex.md", - "08-Inbox/08-Inbox.md", "50-Memos/2025/07/resources/kyhNGvh5iFc9eYXy2YuYWx_FDF8C04E-22D3-4D4C-9ED0-F52A326B9801.jpg", "50-Memos/2025/07/resources/6cb2VU3rkihszQLFDerqA2_2_20250712120414.png", "10-WebClipper/健康休闲", diff --git a/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/obsidian撰写草稿.md b/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/obsidian撰写草稿.md index e8fbcd0c..1fba2161 100644 --- a/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/obsidian撰写草稿.md +++ b/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/obsidian撰写草稿.md @@ -3,7 +3,7 @@ title: obsidian撰写草稿 date: 2022-03-21 18:39:22 status: complete excerpt: 越来越进入正题了,从初学者的角度,尽可能克制地讲一点必要的东西,比如写一个草稿,标题段落列表插图超链接什么的,应该是足够了。 -tags: obsidian入门 +tags: [] rating: ⭐⭐ destination: 03-Projects/黑曜石玩家指南 share: false diff --git a/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/zotero-obsidian联动配置.md b/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/zotero-obsidian联动配置.md index b2a1dfe4..e489fe26 100644 --- a/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/zotero-obsidian联动配置.md +++ b/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/zotero-obsidian联动配置.md @@ -3,7 +3,7 @@ title: zotero-obsidian联动配置 date: 2022-03-21 15:16:11 status: complete excerpt: 果然完成这个内容又花费了一个小时,所以以后可以按照一小时一节的效率来安排时间。 -tags: obsidian入门 +tags: [] rating: ⭐ destination: 03-Projects/黑曜石玩家指南 --- diff --git a/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/使用手机撰写日志.md b/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/使用手机撰写日志.md index b5af9f29..24008be1 100644 --- a/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/使用手机撰写日志.md +++ b/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/使用手机撰写日志.md @@ -3,7 +3,7 @@ title: 使用手机撰写日志 date: 2022-03-22 08:13:34 status: complete excerpt: 这个部分只是作为补充,但又有必要说,因为移动输入也是刚需。 -tags: obsidian入门 +tags: [] rating: ⭐⭐ destination: 03-Projects/黑曜石玩家指南 share: false diff --git a/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/在obsidian中写幻灯片.md b/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/在obsidian中写幻灯片.md index 01fcbf70..68c58a8a 100644 --- a/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/在obsidian中写幻灯片.md +++ b/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/在obsidian中写幻灯片.md @@ -2,7 +2,8 @@ title: 在obsidian中写幻灯片 date: 2022-03-22 12:27:26 excerpt: 这篇就直接就按照幻灯片的方式来写吧 -tags: obsidian入门 ppt +tags: + - ppt rating: ⭐⭐⭐ status: complete destination: 03-Projects/黑曜石玩家指南 diff --git a/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/开箱写日志.md b/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/开箱写日志.md index 2950dca6..fd6aea33 100644 --- a/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/开箱写日志.md +++ b/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/开箱写日志.md @@ -3,7 +3,7 @@ title: 开箱写日志 date: 2022-03-21 16:45:19 status: complete excerpt: 写日志可以非常简单,就是一个按键的事情。 -tags: obsidian入门 +tags: [] rating: ⭐⭐ destination: 03-Projects/黑曜石玩家指南 share: false diff --git a/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/本章小结-恭喜入门obsidian.md b/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/本章小结-恭喜入门obsidian.md index 0d0fa12e..9b69be4e 100644 --- a/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/本章小结-恭喜入门obsidian.md +++ b/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/本章小结-恭喜入门obsidian.md @@ -2,7 +2,7 @@ title: 恭喜入门obsidian date: 2022-03-22 14:39:04 excerpt: 一天时间写完第一章,主要还是靠整理之前的笔记吧。 -tags: obsidian入门 +tags: [] rating: ⭐⭐⭐ status: complete destination: 03-Projects/黑曜石玩家指南 diff --git a/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/每周定期汇总小结.md b/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/每周定期汇总小结.md index 28104997..144f56f0 100644 --- a/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/每周定期汇总小结.md +++ b/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/每周定期汇总小结.md @@ -2,7 +2,7 @@ title: 每周定期汇总小结 date: 2022-03-22 10:18:22 excerpt: 周小结可以说是写日志做笔记中最重要的一件事情了。 -tags: obsidian入门 +tags: [] rating: ⭐⭐⭐ status: complete destination: 03-Projects/黑曜石玩家指南 diff --git a/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/软件下载安装.md b/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/软件下载安装.md index 8a1c948f..4b3c330b 100644 --- a/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/软件下载安装.md +++ b/08-Inbox/99-黑曜石玩家指南/1-obsidian入门/软件下载安装.md @@ -3,7 +3,7 @@ title: 软件下载安装 date: 2022-03-21 14:13:40 status: complete excerpt: 花了一个多小时来写这个玩意,但是作为第一节,可以作为后面章节的模板, 所以构思了一下内容逻辑和内容布局样式,不过总的来说还是值得花点时间的。 -tags: obsidian入门 +tags: [] rating: ⭐⭐⭐ destination: 03-Projects/黑曜石玩家指南 --- diff --git a/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/主题阅读与比较阅读.md b/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/主题阅读与比较阅读.md index 0d040954..1e16a224 100644 --- a/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/主题阅读与比较阅读.md +++ b/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/主题阅读与比较阅读.md @@ -2,7 +2,7 @@ title: 主题阅读与比较阅读 date: 2022-03-26 15:26:07 excerpt: 这是一件需要充分发挥主观能动性的活动,简单的说就是费脑。 -tags: obsidian读文献 +tags: [] rating: ⭐⭐⭐ status: complete destination: 03-Projects/黑曜石玩家指南 diff --git a/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/入库文献泛读.md b/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/入库文献泛读.md index f1f45ac9..7ffb95ac 100644 --- a/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/入库文献泛读.md +++ b/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/入库文献泛读.md @@ -2,7 +2,7 @@ title: 入库文献泛读 date: 2022-03-24 08:50:18 excerpt: 非常简单,获取对文献的初步印象就行。 -tags: obsidian读文献 +tags: [] rating: ⭐⭐ status: complete destination: 03-Projects/黑曜石玩家指南 diff --git a/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/当期文献速览.md b/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/当期文献速览.md index 9baeac62..7f1320a0 100644 --- a/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/当期文献速览.md +++ b/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/当期文献速览.md @@ -2,7 +2,7 @@ title: 当期文献速览 date: 2022-03-23 09:14:42 excerpt: 又是一个小时过去了,还不错,今天就写这一节。 -tags: obsidian读文献 +tags: [] rating: ⭐⭐ status: complete destination: 03-Projects/黑曜石玩家指南 diff --git a/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/本章小结-恭喜习得内功.md b/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/本章小结-恭喜习得内功.md index 8eee6ec1..9a95958f 100644 --- a/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/本章小结-恭喜习得内功.md +++ b/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/本章小结-恭喜习得内功.md @@ -2,7 +2,7 @@ title: 本章小结-恭喜习得内功 date: 2022-03-27 08:28:30 excerpt: 花了5天时间完成了第二章的内容,一共9节,感觉还是有点费劲的。 -tags: obsidian读文献 +tags: [] rating: ⭐ status: complete destination: 03-Projects/黑曜石玩家指南 diff --git a/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/解析文章骨架.md b/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/解析文章骨架.md index 4bb63cd3..45d7b712 100644 --- a/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/解析文章骨架.md +++ b/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/解析文章骨架.md @@ -2,7 +2,7 @@ title: 解析文章骨架 date: 2022-03-25 08:28:51 excerpt: 感觉更多在讲怎么读文献,obsidian的操作就是插入模板而已。 -tags: obsidian读文献 +tags: [] rating: ⭐⭐ status: complete destination: 03-Projects/黑曜石玩家指南 diff --git a/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/跟踪领域内大牛.md b/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/跟踪领域内大牛.md index 1cf34267..8f2724db 100644 --- a/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/跟踪领域内大牛.md +++ b/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/跟踪领域内大牛.md @@ -2,7 +2,7 @@ title: 跟踪领域内大牛 date: 2022-03-26 19:25:09 excerpt: 这部分内容写起来比较轻松。 -tags: obsidian读文献 +tags: [] rating: ⭐⭐⭐ status: complete destination: 03-Projects/黑曜石玩家指南 diff --git a/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/进一步阅读原文.md b/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/进一步阅读原文.md index 75d6fd55..28e5d50d 100644 --- a/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/进一步阅读原文.md +++ b/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/进一步阅读原文.md @@ -2,7 +2,7 @@ title: 进一步阅读原文 date: 2022-03-24 17:40:52 excerpt: 感觉更多是对 zotero 的介绍了。 -tags: obsidian读文献 +tags: [] rating: ⭐ status: complete destination: 03-Projects/黑曜石玩家指南 diff --git a/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/重要综述如何阅读.md b/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/重要综述如何阅读.md index ee083f08..afc1f800 100644 --- a/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/重要综述如何阅读.md +++ b/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/重要综述如何阅读.md @@ -2,7 +2,7 @@ title: 重要综述如何阅读 date: 2022-03-25 10:44:04 excerpt: 所谓的提高效率不过是从实际情况出发有所权衡和取舍。对于重要的文献和综述,再别无他法,只能是老老实实下苦功夫读懂读透。 -tags: obsidian读文献 +tags: [] rating: ⭐⭐⭐ status: complete destination: 03-Projects/黑曜石玩家指南 diff --git a/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/阶段性文献阅读小结.md b/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/阶段性文献阅读小结.md index c8851d43..ae52ebb5 100644 --- a/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/阶段性文献阅读小结.md +++ b/08-Inbox/99-黑曜石玩家指南/2-obsidian读文献/阶段性文献阅读小结.md @@ -2,7 +2,7 @@ title: 阶段性文献阅读小结 date: 2022-03-26 14:14:58 excerpt: 写文献阅读的小结其实跟日志小结的思路是一样的。 -tags: obsidian读文献 +tags: [] rating: ⭐⭐⭐ status: complete destination: 03-Projects/黑曜石玩家指南 diff --git a/08-Inbox/99-黑曜石玩家指南/4-obsidian附录/obsidian快捷键.md b/08-Inbox/99-黑曜石玩家指南/4-obsidian附录/obsidian快捷键.md index 09559a18..d1d9ad01 100644 --- a/08-Inbox/99-黑曜石玩家指南/4-obsidian附录/obsidian快捷键.md +++ b/08-Inbox/99-黑曜石玩家指南/4-obsidian附录/obsidian快捷键.md @@ -2,7 +2,7 @@ title: obsidian快捷键 date: 2022-03-29 13:39:48 excerpt: 掌握常用的快捷键事半功倍。 -tags: obsidian附录 +tags: [] rating: ⭐ status: complete destination: 03-Projects/黑曜石玩家指南 diff --git a/08-Inbox/99-黑曜石玩家指南/4-obsidian附录/obsidian模板库更新方法.md b/08-Inbox/99-黑曜石玩家指南/4-obsidian附录/obsidian模板库更新方法.md index 7859f1db..e1fce207 100644 --- a/08-Inbox/99-黑曜石玩家指南/4-obsidian附录/obsidian模板库更新方法.md +++ b/08-Inbox/99-黑曜石玩家指南/4-obsidian附录/obsidian模板库更新方法.md @@ -2,10 +2,10 @@ title: obsidian模板库更新方法 date: 2022-05-14 14:46:54 excerpt: obsidian和插件的各种功能都在更新,因此这个模板库也得跟上。 -tags: obsidian附录 +tags: [] rating: ⭐⭐ status: complete -destination: 03-99-4 +destination: 03-99-4 share: false obsidianUIMode: source --- diff --git a/08-Inbox/99-黑曜石玩家指南/4-obsidian附录/obsidian第三方插件列表.md b/08-Inbox/99-黑曜石玩家指南/4-obsidian附录/obsidian第三方插件列表.md index ea32315b..a09d93ed 100644 --- a/08-Inbox/99-黑曜石玩家指南/4-obsidian附录/obsidian第三方插件列表.md +++ b/08-Inbox/99-黑曜石玩家指南/4-obsidian附录/obsidian第三方插件列表.md @@ -2,7 +2,7 @@ title: obsidian第三方插件列表 date: 2022-03-29 13:50:06 excerpt: 简单罗列模板库中主要使用的插件。 -tags: obsidian附录 +tags: [] rating: ⭐ status: complete destination: 03-99 diff --git a/08-Inbox/99-黑曜石玩家指南/4-obsidian附录/python代码说明与调试方法.md b/08-Inbox/99-黑曜石玩家指南/4-obsidian附录/python代码说明与调试方法.md index 34e8622e..d11168b5 100644 --- a/08-Inbox/99-黑曜石玩家指南/4-obsidian附录/python代码说明与调试方法.md +++ b/08-Inbox/99-黑曜石玩家指南/4-obsidian附录/python代码说明与调试方法.md @@ -2,10 +2,10 @@ title: python代码说明与调试方法 date: 2022-05-14 15:10:15 excerpt: 本模板库相关工作流依赖于python脚本实现 -tags: obsidian附录 +tags: [] rating: ⭐⭐⭐ status: complete -destination: 03-99-4 +destination: 03-99-4 share: false obsidianUIMode: source --- diff --git a/08-Inbox/99-黑曜石玩家指南/4-obsidian附录/结束语.md b/08-Inbox/99-黑曜石玩家指南/4-obsidian附录/结束语.md index 202ecf7e..6f29f3f0 100644 --- a/08-Inbox/99-黑曜石玩家指南/4-obsidian附录/结束语.md +++ b/08-Inbox/99-黑曜石玩家指南/4-obsidian附录/结束语.md @@ -2,10 +2,10 @@ title: 结束语 date: 2022-05-31 15:19:22 excerpt: 抛砖引玉之作而已。 -tags: obsidian附录 +tags: [] rating: ⭐⭐ status: complete -destination: 03-99-4 +destination: 03-99-4 share: false obsidianUIMode: source --- diff --git a/10-WebClipper/电子书/使用Obsidian打造个人图书馆!.md b/10-WebClipper/电子书/使用Obsidian打造个人图书馆!.md index aaca2f9e..127c6442 100644 --- a/10-WebClipper/电子书/使用Obsidian打造个人图书馆!.md +++ b/10-WebClipper/电子书/使用Obsidian打造个人图书馆!.md @@ -1,13 +1,14 @@ --- -title: "使用Obsidian打造个人图书馆!" -source: "https://zhuanlan.zhihu.com/p/676030394" +title: 使用Obsidian打造个人图书馆! +source: https://zhuanlan.zhihu.com/p/676030394 author: - "[[Jeremiah]]" -published: +published: created: 2025-07-04 -description: "长期以来没有找到符合自己需求的书籍管理工具,手机APP和Excel各有其局限,笔者一开始是使用notion建立个人图书馆,使用的过程中发现notion的文档与文档之间的关联性较差,恰好Obsidian支持双链功能,故此尝试在Ob…" +description: 长期以来没有找到符合自己需求的书籍管理工具,手机APP和Excel各有其局限,笔者一开始是使用notion建立个人图书馆,使用的过程中发现notion的文档与文档之间的关联性较差,恰好Obsidian支持双链功能,故此尝试在Ob… tags: - - "clippings" + - clippings + - 知识库 --- ![使用Obsidian打造个人图书馆!](https://picx.zhimg.com/70/v2-b1faeda2a463bea71bb3fe22d75b599d_1440w.avis?source=172ae18b&biz_tag=Post) diff --git a/10-WebClipper/知识体系/Obsidian 知识体系搭建:入门篇 (一)_牛客网.md b/10-WebClipper/知识体系/Obsidian 知识体系搭建:入门篇 (一)_牛客网.md index 376b2506..3cfa59c6 100644 --- a/10-WebClipper/知识体系/Obsidian 知识体系搭建:入门篇 (一)_牛客网.md +++ b/10-WebClipper/知识体系/Obsidian 知识体系搭建:入门篇 (一)_牛客网.md @@ -208,4 +208,4 @@ _**Windows 与安卓同步**_ **未完待续……** -[#我的实习求职记录#](https://www.nowcoder.com/creation/subject/5e8d2f3639204d0d87734df48cb3fb49)[#23届找工作求助阵地#](https://www.nowcoder.com/creation/subject/77a7cd3045c34927821171bbc13432e1) \ No newline at end of file +[我的实习求职记录](https://www.nowcoder.com/creation/subject/5e8d2f3639204d0d87734df48cb3fb49)[23届找工作求助阵地#](https://www.nowcoder.com/creation/subject/77a7cd3045c34927821171bbc13432e1) \ No newline at end of file diff --git a/10-WebClipper/知识体系/让笔记流动起来——Obsidian重塑知识体系 - 少数派.md b/10-WebClipper/知识体系/让笔记流动起来——Obsidian重塑知识体系 - 少数派.md index aa1b1057..faedbf16 100644 --- a/10-WebClipper/知识体系/让笔记流动起来——Obsidian重塑知识体系 - 少数派.md +++ b/10-WebClipper/知识体系/让笔记流动起来——Obsidian重塑知识体系 - 少数派.md @@ -1,3 +1,4 @@ +#知识库 前言 看完《笔记的方法》一书颇有启发,于是决定将自己的知识体系好好重塑一番,能够更好的为未来的自己“增援”。便有了此文的契机,于是开始整理思考,什么样的笔记方法更适合自己,我需要用什么工具来完成这些知识的整理落地。 @@ -125,7 +126,7 @@ obsidian提供了两个很好的体系:标签与双链。这两大法器,能 标签格式:标签最多三级结构,多级标签(#标签/子标签) -例如: #产品知识/分析报告/竞品分析 +例如: 产品知识/分析报告/竞品分析 4.2 双链构建 --------