Files
securebit-chat/node_modules/dijkstrajs/dijkstra.js
lockbitchat 0f8399ec88 feat(security,ui): self-host React deps, Tailwind, fonts; strict CSP; local QR; better selection state
Replace CDN React/ReactDOM/Babel with local libs; remove Babel and inline scripts
Build Tailwind locally, add safelist; switch to assets/tailwind.css
Self-host Font Awesome and Inter (CSS + woff2); remove external font CDNs
Implement strict CSP (no unsafe-inline/eval; scripts/styles/fonts from self)
Extract inline handlers; move PWA scripts to external files
Add local QR code generation (qrcode lib) and remove api.qrserver.com
Improve SessionTypeSelector visual selection (highlighted background and ring)
Keep PWA working with service worker and offline assets
Refs: CSP hardening, offline-first, no external dependencies
2025-09-08 16:04:58 -04:00

166 lines
5.1 KiB
JavaScript

'use strict';
/******************************************************************************
* Created 2008-08-19.
*
* Dijkstra path-finding functions. Adapted from the Dijkstar Python project.
*
* Copyright (C) 2008
* Wyatt Baldwin <self@wyattbaldwin.com>
* All rights reserved
*
* Licensed under the MIT license.
*
* http://www.opensource.org/licenses/mit-license.php
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*****************************************************************************/
var dijkstra = {
single_source_shortest_paths: function(graph, s, d) {
// Predecessor map for each node that has been encountered.
// node ID => predecessor node ID
var predecessors = {};
// Costs of shortest paths from s to all nodes encountered.
// node ID => cost
var costs = {};
costs[s] = 0;
// Costs of shortest paths from s to all nodes encountered; differs from
// `costs` in that it provides easy access to the node that currently has
// the known shortest path from s.
// XXX: Do we actually need both `costs` and `open`?
var open = dijkstra.PriorityQueue.make();
open.push(s, 0);
var closest,
u, v,
cost_of_s_to_u,
adjacent_nodes,
cost_of_e,
cost_of_s_to_u_plus_cost_of_e,
cost_of_s_to_v,
first_visit;
while (!open.empty()) {
// In the nodes remaining in graph that have a known cost from s,
// find the node, u, that currently has the shortest path from s.
closest = open.pop();
u = closest.value;
cost_of_s_to_u = closest.cost;
// Get nodes adjacent to u...
adjacent_nodes = graph[u] || {};
// ...and explore the edges that connect u to those nodes, updating
// the cost of the shortest paths to any or all of those nodes as
// necessary. v is the node across the current edge from u.
for (v in adjacent_nodes) {
if (adjacent_nodes.hasOwnProperty(v)) {
// Get the cost of the edge running from u to v.
cost_of_e = adjacent_nodes[v];
// Cost of s to u plus the cost of u to v across e--this is *a*
// cost from s to v that may or may not be less than the current
// known cost to v.
cost_of_s_to_u_plus_cost_of_e = cost_of_s_to_u + cost_of_e;
// If we haven't visited v yet OR if the current known cost from s to
// v is greater than the new cost we just found (cost of s to u plus
// cost of u to v across e), update v's cost in the cost list and
// update v's predecessor in the predecessor list (it's now u).
cost_of_s_to_v = costs[v];
first_visit = (typeof costs[v] === 'undefined');
if (first_visit || cost_of_s_to_v > cost_of_s_to_u_plus_cost_of_e) {
costs[v] = cost_of_s_to_u_plus_cost_of_e;
open.push(v, cost_of_s_to_u_plus_cost_of_e);
predecessors[v] = u;
}
}
}
}
if (typeof d !== 'undefined' && typeof costs[d] === 'undefined') {
var msg = ['Could not find a path from ', s, ' to ', d, '.'].join('');
throw new Error(msg);
}
return predecessors;
},
extract_shortest_path_from_predecessor_list: function(predecessors, d) {
var nodes = [];
var u = d;
var predecessor;
while (u) {
nodes.push(u);
predecessor = predecessors[u];
u = predecessors[u];
}
nodes.reverse();
return nodes;
},
find_path: function(graph, s, d) {
var predecessors = dijkstra.single_source_shortest_paths(graph, s, d);
return dijkstra.extract_shortest_path_from_predecessor_list(
predecessors, d);
},
/**
* A very naive priority queue implementation.
*/
PriorityQueue: {
make: function (opts) {
var T = dijkstra.PriorityQueue,
t = {},
key;
opts = opts || {};
for (key in T) {
if (T.hasOwnProperty(key)) {
t[key] = T[key];
}
}
t.queue = [];
t.sorter = opts.sorter || T.default_sorter;
return t;
},
default_sorter: function (a, b) {
return a.cost - b.cost;
},
/**
* Add a new item to the queue and ensure the highest priority element
* is at the front of the queue.
*/
push: function (value, cost) {
var item = {value: value, cost: cost};
this.queue.push(item);
this.queue.sort(this.sorter);
},
/**
* Return the highest priority element in the queue.
*/
pop: function () {
return this.queue.shift();
},
empty: function () {
return this.queue.length === 0;
}
}
};
// node.js module exports
if (typeof module !== 'undefined') {
module.exports = dijkstra;
}