@dotrino/identity 0.20.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +6 -2
- package/vault/avatar.js +65 -0
- package/vault/capabilities.js +5 -43
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dotrino/identity",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Identidad y rating de usuarios compartidos entre apps de Dotrino (vault iframe + postMessage)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -17,7 +17,11 @@
|
|
|
17
17
|
"./capabilities": {
|
|
18
18
|
"import": "./vault/capabilities.js"
|
|
19
19
|
},
|
|
20
|
-
"./
|
|
20
|
+
"./avatar": {
|
|
21
|
+
"import": "./vault/avatar.js"
|
|
22
|
+
},
|
|
23
|
+
"./vault/core.js": "./vault/core.js",
|
|
24
|
+
"./vault/remote.js": "./vault/remote.js"
|
|
21
25
|
},
|
|
22
26
|
"files": [
|
|
23
27
|
"src",
|
package/vault/avatar.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @dotrino/identity/avatar — el AVATAR identicon, solo.
|
|
3
|
+
*
|
|
4
|
+
* Vive aparte de `capabilities.js` a propósito: es una función pura de ~30
|
|
5
|
+
* líneas, sin dependencias, sin crypto y sin vault, pero `capabilities.js`
|
|
6
|
+
* importa `core.js` (55 KB) y `core.js` importa de vuelta `capabilities.js`
|
|
7
|
+
* (dependencia circular). O sea que quien solo quería el identicon —el topbar,
|
|
8
|
+
* la tarjeta de perfil— se arrastraba el vault entero, o dependía de que el
|
|
9
|
+
* bundler podara `core.js` de milagro (ningún paquete declara `sideEffects`).
|
|
10
|
+
*
|
|
11
|
+
* Este subpath da la garantía: importar el avatar cuesta el avatar.
|
|
12
|
+
*
|
|
13
|
+
* NO copies estas funciones dentro de tu app. El identicon es DETERMINISTA a
|
|
14
|
+
* partir del pubkey: si cada app llevara su copia, el mismo usuario podría
|
|
15
|
+
* derivar un avatar distinto según dónde lo miren.
|
|
16
|
+
*
|
|
17
|
+
* `capabilities.js` re-exporta de aquí, así que los importadores viejos siguen
|
|
18
|
+
* funcionando igual.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/** Hash FNV-1a + xorshift. Sin necesidades de seguridad: es decorativo. */
|
|
22
|
+
function _hashSeed (s) {
|
|
23
|
+
let h = 2166136261 >>> 0
|
|
24
|
+
for (let i = 0; i < s.length; i++) { h ^= s.charCodeAt(i); h = Math.imul(h, 16777619) }
|
|
25
|
+
const bytes = []
|
|
26
|
+
let x = (h ^ 0x9e3779b9) >>> 0
|
|
27
|
+
for (let i = 0; i < 16; i++) { x ^= x << 13; x ^= x >>> 17; x ^= x << 5; x >>>= 0; bytes.push(x & 0xff) }
|
|
28
|
+
return { h: h >>> 0, bytes }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Identicon determinista de una semilla (normalmente el pubkey): así cada perfil
|
|
33
|
+
* nace con imagen sin que el usuario tenga que subir nada. Síncrono → usable
|
|
34
|
+
* directo en plantillas. Rejilla 5×5 simétrica sobre una "moneda" redondeada,
|
|
35
|
+
* con color derivado del hash.
|
|
36
|
+
*/
|
|
37
|
+
export function avatarSvg (seed, { size = 80 } = {}) {
|
|
38
|
+
const { h, bytes } = _hashSeed(String(seed || 'dotrino'))
|
|
39
|
+
const hue = h % 360
|
|
40
|
+
const hue2 = (hue + 40) % 360
|
|
41
|
+
const fg = `hsl(${hue} 62% 46%)`
|
|
42
|
+
const bg1 = `hsl(${hue} 48% 95%)`
|
|
43
|
+
const bg2 = `hsl(${hue2} 48% 90%)`
|
|
44
|
+
const cells = 5
|
|
45
|
+
const unit = size / cells
|
|
46
|
+
let rects = ''
|
|
47
|
+
for (let col = 0; col < 3; col++) {
|
|
48
|
+
for (let row = 0; row < cells; row++) {
|
|
49
|
+
if (!(bytes[col * cells + row] & 1)) continue
|
|
50
|
+
for (const c of (col === 2 ? [2] : [col, cells - 1 - col])) {
|
|
51
|
+
rects += `<rect x="${(c * unit).toFixed(2)}" y="${(row * unit).toFixed(2)}" width="${unit.toFixed(2)}" height="${unit.toFixed(2)}"/>`
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const id = 'g' + (h % 100000)
|
|
56
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${size} ${size}" width="${size}" height="${size}">` +
|
|
57
|
+
`<defs><linearGradient id="${id}" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="${bg1}"/><stop offset="1" stop-color="${bg2}"/></linearGradient></defs>` +
|
|
58
|
+
`<rect width="${size}" height="${size}" rx="${(size * 0.5).toFixed(2)}" fill="url(#${id})"/>` +
|
|
59
|
+
`<g fill="${fg}" transform="translate(${(size * 0.12).toFixed(2)} ${(size * 0.12).toFixed(2)}) scale(0.76)">${rects}</g></svg>`
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** El avatar como data-URI listo para `<img src>` o `background-image`. */
|
|
63
|
+
export function avatarDataUri (seed, opts) {
|
|
64
|
+
return 'data:image/svg+xml,' + encodeURIComponent(avatarSvg(seed, opts))
|
|
65
|
+
}
|
package/vault/capabilities.js
CHANGED
|
@@ -99,49 +99,11 @@ export async function commitCode ({ code, dpub, sn }) {
|
|
|
99
99
|
return [...new Uint8Array(h)].map((x) => x.toString(16).padStart(2, '0')).join('')
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
* sobre una "moneda" redondeada, con color derivado del hash.
|
|
108
|
-
*/
|
|
109
|
-
function _hashSeed (s) {
|
|
110
|
-
let h = 2166136261 >>> 0
|
|
111
|
-
for (let i = 0; i < s.length; i++) { h ^= s.charCodeAt(i); h = Math.imul(h, 16777619) }
|
|
112
|
-
const bytes = []
|
|
113
|
-
let x = (h ^ 0x9e3779b9) >>> 0
|
|
114
|
-
for (let i = 0; i < 16; i++) { x ^= x << 13; x ^= x >>> 17; x ^= x << 5; x >>>= 0; bytes.push(x & 0xff) }
|
|
115
|
-
return { h: h >>> 0, bytes }
|
|
116
|
-
}
|
|
117
|
-
export function avatarSvg (seed, { size = 80 } = {}) {
|
|
118
|
-
const { h, bytes } = _hashSeed(String(seed || 'dotrino'))
|
|
119
|
-
const hue = h % 360
|
|
120
|
-
const hue2 = (hue + 40) % 360
|
|
121
|
-
const fg = `hsl(${hue} 62% 46%)`
|
|
122
|
-
const bg1 = `hsl(${hue} 48% 95%)`
|
|
123
|
-
const bg2 = `hsl(${hue2} 48% 90%)`
|
|
124
|
-
const cells = 5
|
|
125
|
-
const unit = size / cells
|
|
126
|
-
let rects = ''
|
|
127
|
-
for (let col = 0; col < 3; col++) {
|
|
128
|
-
for (let row = 0; row < cells; row++) {
|
|
129
|
-
if (!(bytes[col * cells + row] & 1)) continue
|
|
130
|
-
for (const c of (col === 2 ? [2] : [col, cells - 1 - col])) {
|
|
131
|
-
rects += `<rect x="${(c * unit).toFixed(2)}" y="${(row * unit).toFixed(2)}" width="${unit.toFixed(2)}" height="${unit.toFixed(2)}"/>`
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
const id = 'g' + (h % 100000)
|
|
136
|
-
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${size} ${size}" width="${size}" height="${size}">` +
|
|
137
|
-
`<defs><linearGradient id="${id}" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="${bg1}"/><stop offset="1" stop-color="${bg2}"/></linearGradient></defs>` +
|
|
138
|
-
`<rect width="${size}" height="${size}" rx="${(size * 0.5).toFixed(2)}" fill="url(#${id})"/>` +
|
|
139
|
-
`<g fill="${fg}" transform="translate(${(size * 0.12).toFixed(2)} ${(size * 0.12).toFixed(2)}) scale(0.76)">${rects}</g></svg>`
|
|
140
|
-
}
|
|
141
|
-
/** El avatar como data-URI listo para `<img src>` o `background-image`. */
|
|
142
|
-
export function avatarDataUri (seed, opts) {
|
|
143
|
-
return 'data:image/svg+xml,' + encodeURIComponent(avatarSvg(seed, opts))
|
|
144
|
-
}
|
|
102
|
+
// El identicon vive en ./avatar.js (función pura, sin dependencias) y se
|
|
103
|
+
// re-exporta aquí por compatibilidad: importarlo desde este módulo arrastra
|
|
104
|
+
// core.js (55 KB), así que si SOLO quieres el avatar usa el subpath
|
|
105
|
+
// '@dotrino/identity/avatar'.
|
|
106
|
+
export { avatarSvg, avatarDataUri } from './avatar.js'
|
|
145
107
|
|
|
146
108
|
/** Cuerpo canónico del certificado (lo que se firma): el cert SIN la firma. */
|
|
147
109
|
export function delegationBody (cert) {
|