Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

markmap-view

Package Overview
Dependencies
Maintainers
0
Versions
89
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

markmap-view - npm Package Compare versions

Comparing version 0.18.4-alpha.3 to 0.18.4-alpha.4

429

dist/browser/index.js
(function(exports, d32) {
"use strict";
class Hook {
constructor() {
this.listeners = [];
}
tap(fn) {
this.listeners.push(fn);
return () => this.revoke(fn);
}
revoke(fn) {
const i = this.listeners.indexOf(fn);
if (i >= 0) this.listeners.splice(i, 1);
}
revokeAll() {
this.listeners.splice(0);
}
call(...args) {
for (const fn of this.listeners) {
fn(...args);
}
}
}
const uniqId = Math.random().toString(36).slice(2, 8);
let globalIndex = 0;
function getId() {
globalIndex += 1;
return `mm-${uniqId}-${globalIndex}`;
}
function noop() {
}
function walkTree(tree, callback) {
const walk = (item, parent) => callback(
item,
() => {
var _a;
return (_a = item.children) == null ? void 0 : _a.map((child) => walk(child, item));
},
parent
);
return walk(tree);
}
function addClass(className, ...rest) {
const classList = (className || "").split(" ").filter(Boolean);
rest.forEach((item) => {
if (item && classList.indexOf(item) < 0) classList.push(item);
});
return classList.join(" ");
}
function childSelector(filter) {
if (typeof filter === "string") {
const tagName = filter;
filter = (el) => el.tagName === tagName;
}
const filterFn = filter;
return function selector() {
let nodes = Array.from(this.childNodes);
if (filterFn) nodes = nodes.filter((node) => filterFn(node));
return nodes;
};
}
function defer() {
const obj = {};
obj.promise = new Promise((resolve, reject) => {
obj.resolve = resolve;
obj.reject = reject;
});
return obj;
}
function memoize(fn) {
const cache = {};
return function memoized(...args) {
const key = `${args[0]}`;
let data = cache[key];
if (!data) {
data = {
value: fn(...args)
};
cache[key] = data;
}
return data.value;
};
}
function debounce(fn, time) {
const state = {
timer: 0
};
function reset() {
if (state.timer) {
window.clearTimeout(state.timer);
state.timer = 0;
}
}
function run() {
reset();
if (state.args) state.result = fn(...state.args);
}
return function debounced(...args) {
reset();
state.args = args;
state.timer = window.setTimeout(run, time);
return state.result;
};
}
/*! @gera2ld/jsx-dom v2.2.2 | ISC License */
const VTYPE_ELEMENT = 1;
const VTYPE_FUNCTION = 2;
const SVG_NS = "http://www.w3.org/2000/svg";
const XLINK_NS = "http://www.w3.org/1999/xlink";
const NS_ATTRS = {
show: XLINK_NS,
actuate: XLINK_NS,
href: XLINK_NS
};
const isLeaf = (c) => typeof c === "string" || typeof c === "number";
const isElement = (c) => (c == null ? void 0 : c.vtype) === VTYPE_ELEMENT;
const isRenderFunction = (c) => (c == null ? void 0 : c.vtype) === VTYPE_FUNCTION;
function h(type, props, ...children) {
props = Object.assign({}, props, {
children: children.length === 1 ? children[0] : children
});
return jsx(type, props);
}
function jsx(type, props) {
let vtype;
if (typeof type === "string") vtype = VTYPE_ELEMENT;
else if (typeof type === "function") vtype = VTYPE_FUNCTION;
else throw new Error("Invalid VNode type");
return {
vtype,
type,
props
};
}
function Fragment(props) {
return props.children;
}
const DEFAULT_ENV = {
isSvg: false
};
function insertDom(parent, nodes) {
if (!Array.isArray(nodes)) nodes = [nodes];
nodes = nodes.filter(Boolean);
if (nodes.length) parent.append(...nodes);
}
function mountAttributes(domElement, props, env) {
for (const key in props) {
if (key === "key" || key === "children" || key === "ref") continue;
if (key === "dangerouslySetInnerHTML") {
domElement.innerHTML = props[key].__html;
} else if (key === "innerHTML" || key === "textContent" || key === "innerText" || key === "value" && ["textarea", "select"].includes(domElement.tagName)) {
const value = props[key];
if (value != null) domElement[key] = value;
} else if (key.startsWith("on")) {
domElement[key.toLowerCase()] = props[key];
} else {
setDOMAttribute(domElement, key, props[key], env.isSvg);
}
}
}
const attrMap = {
className: "class",
labelFor: "for"
};
function setDOMAttribute(el, attr, value, isSVG) {
attr = attrMap[attr] || attr;
if (value === true) {
el.setAttribute(attr, "");
} else if (value === false) {
el.removeAttribute(attr);
} else {
const namespace = isSVG ? NS_ATTRS[attr] : void 0;
if (namespace !== void 0) {
el.setAttributeNS(namespace, attr, value);
} else {
el.setAttribute(attr, value);
}
}
}
function flatten(arr) {
return arr.reduce((prev, item) => prev.concat(item), []);
}
function mountChildren(children, env) {
return Array.isArray(children) ? flatten(children.map((child) => mountChildren(child, env))) : mount(children, env);
}
function mount(vnode, env = DEFAULT_ENV) {
if (vnode == null || typeof vnode === "boolean") {
return null;
}
if (vnode instanceof Node) {
return vnode;
}
if (isRenderFunction(vnode)) {
const {
type,
props
} = vnode;
if (type === Fragment) {
const node = document.createDocumentFragment();
if (props.children) {
const children = mountChildren(props.children, env);
insertDom(node, children);
}
return node;
}
const childVNode = type(props);
return mount(childVNode, env);
}
if (isLeaf(vnode)) {
return document.createTextNode(`${vnode}`);
}
if (isElement(vnode)) {
let node;
const {
type,
props
} = vnode;
if (!env.isSvg && type === "svg") {
env = Object.assign({}, env, {
isSvg: true
});
}
if (!env.isSvg) {
node = document.createElement(type);
} else {
node = document.createElementNS(SVG_NS, type);
}
mountAttributes(node, props, env);
if (props.children) {
let childEnv = env;
if (env.isSvg && type === "foreignObject") {
childEnv = Object.assign({}, childEnv, {
isSvg: false
});
}
const children = mountChildren(props.children, childEnv);
if (children != null) insertDom(node, children);
}
const {
ref
} = props;
if (typeof ref === "function") ref(node);
return node;
}
throw new Error("mount: Invalid Vnode!");
}
function mountDom(vnode) {
return mount(vnode);
}
function hm(...args) {
return mountDom(h(...args));
}
const memoizedPreloadJS = memoize((url) => {
document.head.append(
hm("link", {
rel: "preload",
as: "script",
href: url
})
);
});
const jsCache = {};
const cssCache = {};
async function loadJSItem(item, context) {
var _a;
const src = item.type === "script" && ((_a = item.data) == null ? void 0 : _a.src) || "";
item.loaded || (item.loaded = jsCache[src]);
if (!item.loaded) {
const deferred = defer();
item.loaded = deferred.promise;
if (item.type === "script") {
document.head.append(
hm("script", {
...item.data,
onLoad: () => deferred.resolve(),
onError: deferred.reject
})
);
if (!src) {
deferred.resolve();
} else {
jsCache[src] = item.loaded;
}
}
if (item.type === "iife") {
const { fn, getParams } = item.data;
fn(...(getParams == null ? void 0 : getParams(context)) || []);
deferred.resolve();
}
}
await item.loaded;
}
async function loadCSSItem(item) {
const url = item.type === "stylesheet" && item.data.href || "";
item.loaded || (item.loaded = cssCache[url]);
if (!item.loaded) {
const deferred = defer();
item.loaded = deferred.promise;
if (url) cssCache[url] = item.loaded;
if (item.type === "style") {
document.head.append(
hm("style", {
textContent: item.data
})
);
deferred.resolve();
} else if (url) {
document.head.append(
hm("link", {
rel: "stylesheet",
...item.data
})
);
fetch(url).then((res) => {
if (res.ok) return res.text();
throw res;
}).then(() => deferred.resolve(), deferred.reject);
}
}
await item.loaded;
}
async function loadJS(items, context) {
items.forEach((item) => {
var _a;
if (item.type === "script" && ((_a = item.data) == null ? void 0 : _a.src)) {
memoizedPreloadJS(item.data.src);
}
});
context = {
getMarkmap: () => window.markmap,
...context
};
for (const item of items) {
await loadJSItem(item, context);
}
}
async function loadCSS(items) {
await Promise.all(items.map((item) => loadCSSItem(item)));
}
const isMacintosh = typeof navigator !== "undefined" && navigator.userAgent.includes("Macintosh");

@@ -533,3 +196,3 @@ const defaultColorFn = d32.scaleOrdinal(d32.schemeCategory10);

function hierarchy(data, children) {
var root = new Node$1(data), valued = +data.value && (root.value = data.value), node, nodes = [root], child, childs, i, n;
var root = new Node(data), valued = +data.value && (root.value = data.value), node, nodes = [root], child, childs, i, n;
if (children == null) children = defaultChildren;

@@ -541,3 +204,3 @@ while (node = nodes.pop()) {

for (i = n - 1; i >= 0; --i) {
nodes.push(child = node.children[i] = new Node$1(childs[i]));
nodes.push(child = node.children[i] = new Node(childs[i]));
child.parent = node;

@@ -565,3 +228,3 @@ child.depth = node.depth + 1;

}
function Node$1(data) {
function Node(data) {
this.data = data;

@@ -571,4 +234,4 @@ this.depth = this.height = 0;

}
Node$1.prototype = hierarchy.prototype = {
constructor: Node$1,
Node.prototype = hierarchy.prototype = {
constructor: Node,
count: node_count,

@@ -949,2 +612,82 @@ each: node_each,

};
class Hook {
constructor() {
this.listeners = [];
}
tap(fn) {
this.listeners.push(fn);
return () => this.revoke(fn);
}
revoke(fn) {
const i = this.listeners.indexOf(fn);
if (i >= 0) this.listeners.splice(i, 1);
}
revokeAll() {
this.listeners.splice(0);
}
call(...args) {
for (const fn of this.listeners) {
fn(...args);
}
}
}
const uniqId = Math.random().toString(36).slice(2, 8);
let globalIndex = 0;
function getId() {
globalIndex += 1;
return `mm-${uniqId}-${globalIndex}`;
}
function noop() {
}
function walkTree(tree, callback) {
const walk = (item, parent) => callback(
item,
() => {
var _a;
return (_a = item.children) == null ? void 0 : _a.map((child) => walk(child, item));
},
parent
);
return walk(tree);
}
function addClass(className, ...rest) {
const classList = (className || "").split(" ").filter(Boolean);
rest.forEach((item) => {
if (item && classList.indexOf(item) < 0) classList.push(item);
});
return classList.join(" ");
}
function childSelector(filter) {
if (typeof filter === "string") {
const tagName = filter;
filter = (el) => el.tagName === tagName;
}
const filterFn = filter;
return function selector() {
let nodes = Array.from(this.childNodes);
if (filterFn) nodes = nodes.filter((node) => filterFn(node));
return nodes;
};
}
function debounce(fn, time) {
const state = {
timer: 0
};
function reset() {
if (state.timer) {
window.clearTimeout(state.timer);
state.timer = 0;
}
}
function run() {
reset();
if (state.args) state.result = fn(...state.args);
}
return function debounced(...args) {
reset();
state.args = args;
state.timer = window.setTimeout(run, time);
return state.result;
};
}
const css = ".markmap {\n --markmap-max-width: 9999px;\n --markmap-a-color: #0097e6;\n --markmap-a-hover-color: #00a8ff;\n --markmap-code-bg: #f0f0f0;\n --markmap-code-color: #555;\n --markmap-highlight-bg: #ffeaa7;\n --markmap-table-border: 1px solid currentColor;\n --markmap-font: 300 16px/20px sans-serif;\n --markmap-circle-open-bg: #fff;\n --markmap-text-color: #333;\n\n font: var(--markmap-font);\n color: var(--markmap-text-color);\n}\n\n .markmap-link {\n fill: none;\n }\n\n .markmap-node > circle {\n cursor: pointer;\n }\n\n .markmap-foreign {\n display: inline-block;\n }\n\n .markmap-foreign p {\n margin: 0;\n }\n\n .markmap-foreign a {\n color: var(--markmap-a-color);\n }\n\n .markmap-foreign a:hover {\n color: var(--markmap-a-hover-color);\n }\n\n .markmap-foreign code {\n padding: 0.25em;\n font-size: calc(1em - 2px);\n color: var(--markmap-code-color);\n background-color: var(--markmap-code-bg);\n border-radius: 2px;\n }\n\n .markmap-foreign pre {\n margin: 0;\n }\n\n .markmap-foreign pre > code {\n display: block;\n }\n\n .markmap-foreign del {\n text-decoration: line-through;\n }\n\n .markmap-foreign em {\n font-style: italic;\n }\n\n .markmap-foreign strong {\n font-weight: bold;\n }\n\n .markmap-foreign mark {\n background: var(--markmap-highlight-bg);\n }\n\n .markmap-foreign table,\n .markmap-foreign th,\n .markmap-foreign td {\n border-collapse: collapse;\n border: var(--markmap-table-border);\n }\n\n .markmap-foreign img {\n display: inline-block;\n }\n\n .markmap-foreign svg {\n fill: currentColor;\n }\n\n .markmap-foreign > div {\n width: var(--markmap-max-width);\n text-align: left;\n }\n\n .markmap-foreign > div > div {\n display: inline-block;\n }\n\n.markmap-dark .markmap {\n --markmap-code-bg: #1a1b26;\n --markmap-code-color: #ddd;\n --markmap-circle-open-bg: #444;\n --markmap-text-color: #eee;\n}\n";

@@ -1449,4 +1192,2 @@ const globalCSS = css;

exports.isMacintosh = isMacintosh;
exports.loadCSS = loadCSS;
exports.loadJS = loadJS;
exports.refreshHook = refreshHook;

@@ -1453,0 +1194,0 @@ exports.simpleHash = simpleHash;

@@ -1,2 +0,1 @@

export { loadJS, loadCSS } from 'markmap-common';
export * from './types';

@@ -3,0 +2,0 @@ export * from './constants';

49

dist/index.js

@@ -1,5 +0,4 @@

import { Hook as at, getId as lt, debounce as ct, addClass as ht, walkTree as C, childSelector as v, noop as w } from "markmap-common";
import { loadCSS as xe, loadJS as ye } from "markmap-common";
import { scaleOrdinal as G, schemeCategory10 as dt, linkHorizontal as pt, zoomTransform as S, select as ut, zoom as mt, min as P, max as W, zoomIdentity as gt, minIndex as ft } from "d3";
const V = typeof navigator < "u" && navigator.userAgent.includes("Macintosh"), xt = G(dt), U = {
import { scaleOrdinal as G, schemeCategory10 as at, linkHorizontal as lt, zoomTransform as w, select as ct, zoom as ht, min as P, max as W, zoomIdentity as dt, minIndex as pt } from "d3";
import { Hook as ut, getId as mt, debounce as gt, addClass as ft, walkTree as C, childSelector as v, noop as S } from "markmap-common";
const V = typeof navigator < "u" && navigator.userAgent.includes("Macintosh"), xt = G(at), U = {
autoFit: !1,

@@ -100,3 +99,3 @@ color: (e) => {

}
function Ct(e) {
function wt(e) {
return this.eachAfter(function(t) {

@@ -107,3 +106,3 @@ for (var s = +e(t.data) || 0, n = t.children, o = n && n.length; --o >= 0; ) s += n[o].value;

}
function wt(e) {
function Ct(e) {
return this.eachBefore(function(t) {

@@ -182,4 +181,4 @@ t.children && t.children.sort(e);

eachBefore: zt,
sum: Ct,
sort: wt,
sum: wt,
sort: Ct,
path: St,

@@ -453,3 +452,3 @@ ancestors: Xt,

};
}, Q = ".markmap{--markmap-max-width: 9999px;--markmap-a-color: #0097e6;--markmap-a-hover-color: #00a8ff;--markmap-code-bg: #f0f0f0;--markmap-code-color: #555;--markmap-highlight-bg: #ffeaa7;--markmap-table-border: 1px solid currentColor;--markmap-font: 300 16px/20px sans-serif;--markmap-circle-open-bg: #fff;--markmap-text-color: #333;font:var(--markmap-font);color:var(--markmap-text-color)}.markmap-link{fill:none}.markmap-node>circle{cursor:pointer}.markmap-foreign{display:inline-block}.markmap-foreign p{margin:0}.markmap-foreign a{color:var(--markmap-a-color)}.markmap-foreign a:hover{color:var(--markmap-a-hover-color)}.markmap-foreign code{padding:.25em;font-size:calc(1em - 2px);color:var(--markmap-code-color);background-color:var(--markmap-code-bg);border-radius:2px}.markmap-foreign pre{margin:0}.markmap-foreign pre>code{display:block}.markmap-foreign del{text-decoration:line-through}.markmap-foreign em{font-style:italic}.markmap-foreign strong{font-weight:700}.markmap-foreign mark{background:var(--markmap-highlight-bg)}.markmap-foreign table,.markmap-foreign th,.markmap-foreign td{border-collapse:collapse;border:var(--markmap-table-border)}.markmap-foreign img{display:inline-block}.markmap-foreign svg{fill:currentColor}.markmap-foreign>div{width:var(--markmap-max-width);text-align:left}.markmap-foreign>div>div{display:inline-block}.markmap-dark .markmap{--markmap-code-bg: #1a1b26;--markmap-code-color: #ddd;--markmap-circle-open-bg: #444;--markmap-text-color: #eee}", me = Q, j = pt();
}, Q = ".markmap{--markmap-max-width: 9999px;--markmap-a-color: #0097e6;--markmap-a-hover-color: #00a8ff;--markmap-code-bg: #f0f0f0;--markmap-code-color: #555;--markmap-highlight-bg: #ffeaa7;--markmap-table-border: 1px solid currentColor;--markmap-font: 300 16px/20px sans-serif;--markmap-circle-open-bg: #fff;--markmap-text-color: #333;font:var(--markmap-font);color:var(--markmap-text-color)}.markmap-link{fill:none}.markmap-node>circle{cursor:pointer}.markmap-foreign{display:inline-block}.markmap-foreign p{margin:0}.markmap-foreign a{color:var(--markmap-a-color)}.markmap-foreign a:hover{color:var(--markmap-a-hover-color)}.markmap-foreign code{padding:.25em;font-size:calc(1em - 2px);color:var(--markmap-code-color);background-color:var(--markmap-code-bg);border-radius:2px}.markmap-foreign pre{margin:0}.markmap-foreign pre>code{display:block}.markmap-foreign del{text-decoration:line-through}.markmap-foreign em{font-style:italic}.markmap-foreign strong{font-weight:700}.markmap-foreign mark{background:var(--markmap-highlight-bg)}.markmap-foreign table,.markmap-foreign th,.markmap-foreign td{border-collapse:collapse;border:var(--markmap-table-border)}.markmap-foreign img{display:inline-block}.markmap-foreign svg{fill:currentColor}.markmap-foreign>div{width:var(--markmap-max-width);text-align:left}.markmap-foreign>div>div{display:inline-block}.markmap-dark .markmap{--markmap-code-bg: #1a1b26;--markmap-code-color: #ddd;--markmap-circle-open-bg: #444;--markmap-text-color: #eee}", me = Q, j = lt();
function I(e) {

@@ -459,3 +458,3 @@ return Math.max(4 - 2 * e.state.depth, 1.5);

function K(e, t) {
const s = ft(e, t);
const s = pt(e, t);
return e[s];

@@ -466,3 +465,3 @@ }

}
const le = new at();
const le = new ut();
class tt {

@@ -475,3 +474,3 @@ constructor(t, s) {

n.preventDefault();
const o = S(this.svg.node()), a = o.translate(
const o = w(this.svg.node()), a = o.translate(
-n.deltaX / o.k,

@@ -484,7 +483,7 @@ -n.deltaY / o.k

(V ? n.metaKey : n.ctrlKey) && (a = !a), this.toggleNode(o, a);
}, this.ensureView = this.ensureVisible, this.svg = t.datum ? t : ut(t), this.styleNode = this.svg.append("style"), this.zoom = mt().filter((n) => this.options.scrollForPan && n.type === "wheel" ? n.ctrlKey && !n.button : (!n.ctrlKey || n.type === "wheel") && !n.button).on("zoom", this.handleZoom), this.setOptions(s), this.state = {
id: this.options.id || this.svg.attr("id") || lt(),
}, this.ensureView = this.ensureVisible, this.svg = t.datum ? t : ct(t), this.styleNode = this.svg.append("style"), this.zoom = ht().filter((n) => this.options.scrollForPan && n.type === "wheel" ? n.ctrlKey && !n.button : (!n.ctrlKey || n.type === "wheel") && !n.button).on("zoom", this.handleZoom), this.setOptions(s), this.state = {
id: this.options.id || this.svg.attr("id") || mt(),
rect: { x1: 0, y1: 0, x2: 0, y2: 0 }
}, this.g = this.svg.append("g"), this.observer = new ResizeObserver(
ct(() => {
gt(() => {
this.renderData();

@@ -507,3 +506,3 @@ }, 100)

"class",
ht(this.svg.attr("class"), "markmap", this.state.id)
ft(this.svg.attr("class"), "markmap", this.state.id)
);

@@ -715,7 +714,7 @@ const t = this.getStyleContent();

t
), g = gt.translate(
), g = dt.translate(
(n - h * m) / 2 - l * m,
(o - u * m) / 2 - r * m
).scale(m);
return this.transition(this.svg).call(this.zoom.transform, g).end().catch(w);
return this.transition(this.svg).call(this.zoom.transform, g).end().catch(S);
}

@@ -738,3 +737,3 @@ findElement(t) {

if (!n) return;
const o = this.svg.node(), a = o.getBoundingClientRect(), l = S(o), [r, c] = [
const o = this.svg.node(), a = o.getBoundingClientRect(), l = w(o), [r, c] = [
n.state.rect.x,

@@ -754,3 +753,3 @@ n.state.rect.x + n.state.rect.width + 2

const k = l.translate(y, x);
return this.transition(this.svg).call(this.zoom.transform, k).end().catch(w);
return this.transition(this.svg).call(this.zoom.transform, k).end().catch(S);
}

@@ -762,3 +761,3 @@ }

if (!n) return;
const o = this.svg.node(), a = o.getBoundingClientRect(), l = S(o), r = (n.state.rect.x + n.state.rect.width / 2) * l.k + l.x, c = (n.state.rect.y + n.state.rect.height / 2) * l.k + l.y, p = {
const o = this.svg.node(), a = o.getBoundingClientRect(), l = w(o), r = (n.state.rect.x + n.state.rect.width / 2) * l.k + l.x, c = (n.state.rect.y + n.state.rect.height / 2) * l.k + l.y, p = {
left: 0,

@@ -772,3 +771,3 @@ right: 0,

const x = l.translate(m, g);
return this.transition(this.svg).call(this.zoom.transform, x).end().catch(w);
return this.transition(this.svg).call(this.zoom.transform, x).end().catch(S);
}

@@ -780,7 +779,7 @@ }

async rescale(t) {
const s = this.svg.node(), { width: n, height: o } = s.getBoundingClientRect(), a = n / 2, l = o / 2, r = S(s), c = r.translate(
const s = this.svg.node(), { width: n, height: o } = s.getBoundingClientRect(), a = n / 2, l = o / 2, r = w(s), c = r.translate(
(a - r.x) * (1 - t) / r.k,
(l - r.y) * (1 - t) / r.k
).scale(t);
return this.transition(this.svg).call(this.zoom.transform, c).end().catch(w);
return this.transition(this.svg).call(this.zoom.transform, c).end().catch(S);
}

@@ -806,6 +805,4 @@ destroy() {

V as isMacintosh,
xe as loadCSS,
ye as loadJS,
le as refreshHook,
yt as simpleHash
};
{
"name": "markmap-view",
"version": "0.18.4-alpha.3+be73b69",
"version": "0.18.4-alpha.4+8f90d3c",
"description": "View markmaps in browser",

@@ -54,3 +54,3 @@ "author": "Gerald <gera2ld@live.com>",

},
"gitHead": "be73b698cdf408b0a16aea2fe860fe92d8c458bc"
"gitHead": "8f90d3cef5816b56ad80fc1db35caea8df330789"
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc