├── .gitattributes ├── .gitignore ├── .vscode └── launch.json ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── database-er-diagram.odg ├── database-normalization.ods ├── rustfmt.toml └── src ├── brn_tui ├── input_mode.rs ├── input_string.rs ├── main.rs ├── mod.rs ├── stateful_list.rs └── tui_data.rs ├── collection_tool.rs ├── database.rs ├── directory.rs ├── file_utility.rs ├── for_zettelkasten_dir ├── cytoscape │ ├── .browserslist │ ├── .eslintrc.json │ ├── .github │ │ ├── ISSUE_TEMPLATE.md │ │ ├── ISSUE_TEMPLATE │ │ │ ├── bug_report.md │ │ │ └── feature_request.md │ │ ├── PULL_REQUEST_TEMPLATE.md │ │ ├── stale.yml │ │ └── workflows │ │ │ └── tests.yml │ ├── .size-snapshot.json │ ├── .travis.yml │ ├── LICENSE │ ├── README.md │ ├── SECURITY.md │ ├── dist │ │ ├── cytoscape.cjs.js │ │ ├── cytoscape.esm.js │ │ ├── cytoscape.esm.min.js │ │ ├── cytoscape.min.js │ │ └── cytoscape.umd.js │ ├── license-update.js │ ├── package.json │ ├── rollup.config.js │ └── src │ │ ├── animation.js │ │ ├── cjs.js │ │ ├── collection │ │ ├── algorithms │ │ │ ├── a-star.js │ │ │ ├── affinity-propagation.js │ │ │ ├── bellman-ford.js │ │ │ ├── betweenness-centrality.js │ │ │ ├── bfs-dfs.js │ │ │ ├── closeness-centrality.js │ │ │ ├── clustering-distances.js │ │ │ ├── degree-centrality.js │ │ │ ├── dijkstra.js │ │ │ ├── floyd-warshall.js │ │ │ ├── hierarchical-clustering.js │ │ │ ├── hierholzer.js │ │ │ ├── hopcroft-tarjan-biconnected.js │ │ │ ├── index.js │ │ │ ├── k-clustering.js │ │ │ ├── karger-stein.js │ │ │ ├── kruskal.js │ │ │ ├── markov-clustering.js │ │ │ ├── page-rank.js │ │ │ └── tarjan-strongly-connected.js │ │ ├── animation.js │ │ ├── cache-traversal-call.js │ │ ├── class.js │ │ ├── comparators.js │ │ ├── compounds.js │ │ ├── data.js │ │ ├── degree.js │ │ ├── dimensions │ │ │ ├── bounds.js │ │ │ ├── edge-points.js │ │ │ ├── index.js │ │ │ ├── position.js │ │ │ └── width-height.js │ │ ├── element.js │ │ ├── events.js │ │ ├── filter.js │ │ ├── group.js │ │ ├── index.js │ │ ├── iteration.js │ │ ├── layout.js │ │ ├── style.js │ │ ├── switch-functions.js │ │ ├── traversing.js │ │ └── zsort.js │ │ ├── core │ │ ├── add-remove.js │ │ ├── animation │ │ │ ├── cubic-bezier.js │ │ │ ├── ease.js │ │ │ ├── easings.js │ │ │ ├── index.js │ │ │ ├── spring.js │ │ │ ├── start.js │ │ │ ├── step-all.js │ │ │ └── step.js │ │ ├── data.js │ │ ├── events.js │ │ ├── export.js │ │ ├── index.js │ │ ├── layout.js │ │ ├── notification.js │ │ ├── renderer.js │ │ ├── search.js │ │ ├── style.js │ │ └── viewport.js │ │ ├── define │ │ ├── animation.js │ │ ├── data.js │ │ ├── events.js │ │ └── index.js │ │ ├── emitter.js │ │ ├── event.js │ │ ├── extension.js │ │ ├── extensions │ │ ├── index.js │ │ ├── layout │ │ │ ├── breadthfirst.js │ │ │ ├── circle.js │ │ │ ├── concentric.js │ │ │ ├── cose.js │ │ │ ├── grid.js │ │ │ ├── index.js │ │ │ ├── null.js │ │ │ ├── preset.js │ │ │ └── random.js │ │ └── renderer │ │ │ ├── base │ │ │ ├── arrow-shapes.js │ │ │ ├── coord-ele-math │ │ │ │ ├── coords.js │ │ │ │ ├── edge-arrows.js │ │ │ │ ├── edge-control-points.js │ │ │ │ ├── edge-endpoints.js │ │ │ │ ├── edge-projection.js │ │ │ │ ├── index.js │ │ │ │ ├── labels.js │ │ │ │ ├── nodes.js │ │ │ │ ├── rendered-style.js │ │ │ │ └── z-ordering.js │ │ │ ├── images.js │ │ │ ├── index.js │ │ │ ├── load-listeners.js │ │ │ ├── node-shapes.js │ │ │ └── redraw.js │ │ │ ├── canvas │ │ │ ├── arrow-shapes.js │ │ │ ├── drawing-edges.js │ │ │ ├── drawing-elements.js │ │ │ ├── drawing-images.js │ │ │ ├── drawing-label-text.js │ │ │ ├── drawing-nodes.js │ │ │ ├── drawing-redraw.js │ │ │ ├── drawing-shapes.js │ │ │ ├── ele-texture-cache-lookup.js │ │ │ ├── ele-texture-cache.js │ │ │ ├── export-image.js │ │ │ ├── index.js │ │ │ ├── layered-texture-cache.js │ │ │ ├── node-shapes.js │ │ │ └── texture-cache-defs.js │ │ │ ├── index.js │ │ │ └── null │ │ │ └── index.js │ │ ├── heap.js │ │ ├── index.js │ │ ├── is.js │ │ ├── map.js │ │ ├── math.js │ │ ├── promise.js │ │ ├── selector │ │ ├── data.js │ │ ├── expressions.js │ │ ├── index.js │ │ ├── matching.js │ │ ├── new-query.js │ │ ├── parse.js │ │ ├── query-type-match.js │ │ ├── state.js │ │ ├── tokens.js │ │ └── type.js │ │ ├── set.js │ │ ├── style │ │ ├── apply.js │ │ ├── bypass.js │ │ ├── container.js │ │ ├── get-for-ele.js │ │ ├── index.js │ │ ├── json.js │ │ ├── parse.js │ │ ├── properties.js │ │ └── string-sheet.js │ │ ├── stylesheet.js │ │ ├── test.js │ │ ├── util │ │ ├── colors.js │ │ ├── extend.js │ │ ├── hash.js │ │ ├── index.js │ │ ├── maps.js │ │ ├── memoize.js │ │ ├── regex.js │ │ ├── sort.js │ │ ├── strings.js │ │ └── timing.js │ │ ├── version.js │ │ └── window.js ├── graph.js ├── index.html ├── note-template.md └── style.css ├── graph ├── graph_edge.rs ├── graph_node.rs ├── main.rs └── mod.rs ├── history.rs ├── main.rs ├── message.rs ├── note.rs ├── note_link.rs ├── note_metadata.rs ├── note_property.rs ├── note_tagging.rs ├── note_type.rs ├── note_utility.rs └── settings.rs /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to line feed line endings 3 | # ( ~~automatically normalize line endings~~ ). 4 | ############################################################################### 5 | #* text=auto 6 | * text eol=lf 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | target/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | 13 | # MSVC Windows builds of rustc generate these, which store debugging information 14 | *.pdb 15 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "lldb", 9 | "request": "launch", 10 | "name": "Debug", 11 | "program": "${workspaceFolder}/target/debug/brn", 12 | "args": ["tui"], 13 | "cwd": "/home/robert/zettelkasten" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "brn" 3 | version = "2.3.3" 4 | authors = ["Robert Lag InputString { 8 | InputString { 9 | text: String::from(pre_text), 10 | pre_text_length: pre_text.len(), 11 | } 12 | } 13 | 14 | pub fn push(&mut self, c: char) { 15 | self.text.push(c); 16 | } 17 | 18 | pub fn pop(&mut self) { 19 | if self.text.len() > self.pre_text_length { 20 | self.text.pop(); 21 | } 22 | } 23 | 24 | pub fn get_displayed_text(&self) -> String { 25 | return self.text.clone(); 26 | } 27 | 28 | pub fn get_content_text(&self) -> String { 29 | return self 30 | .text 31 | .chars() 32 | .into_iter() 33 | .skip(self.pre_text_length) 34 | .collect(); 35 | } 36 | 37 | pub fn set_pre_text(&mut self, pre_text: &str) { 38 | self.text = String::from(pre_text); 39 | self.pre_text_length = pre_text.len(); 40 | } 41 | 42 | pub fn clear(&mut self) { 43 | while self.text.len() > self.pre_text_length { 44 | self.text.pop(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/brn_tui/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod input_mode; 2 | pub mod input_string; 3 | pub mod main; 4 | pub mod stateful_list; 5 | pub mod tui_data; 6 | -------------------------------------------------------------------------------- /src/brn_tui/stateful_list.rs: -------------------------------------------------------------------------------- 1 | use tui::widgets::ListState; 2 | 3 | pub struct StatefulList { 4 | state: ListState, 5 | items: Vec, 6 | } 7 | 8 | impl Default for StatefulList { 9 | fn default() -> StatefulList { 10 | StatefulList::with_items(Vec::new()) 11 | } 12 | } 13 | 14 | impl StatefulList { 15 | pub fn with_items(items: Vec) -> StatefulList { 16 | StatefulList { 17 | state: ListState::default(), 18 | items, 19 | } 20 | } 21 | 22 | pub fn replace_items_with(&mut self, items: Vec) { 23 | self.items = items; 24 | self.state = ListState::default(); 25 | } 26 | 27 | pub fn select(&mut self, index: Option) { 28 | self.state.select(index); 29 | } 30 | 31 | pub fn selected(&mut self) -> Option { 32 | self.state.selected() 33 | } 34 | 35 | pub fn selected_item(&mut self) -> Option<&T> { 36 | if self.items.is_empty() { 37 | return None; 38 | } 39 | 40 | if let Some(selected_index) = self.selected() { 41 | return Some(&self.items[selected_index]); 42 | } else { 43 | return None; 44 | } 45 | } 46 | 47 | pub fn next(&mut self) { 48 | if self.items.len() == 0 { 49 | return; 50 | } 51 | 52 | let next_index = match self.selected() { 53 | Some(i) => { 54 | if i >= self.items.len() - 1 { 55 | self.items.len() - 1 56 | } else { 57 | i + 1 58 | } 59 | } 60 | None => 0, 61 | }; 62 | self.state.select(Some(next_index)); 63 | } 64 | 65 | pub fn previous(&mut self) { 66 | if self.items.len() == 0 { 67 | return; 68 | } 69 | 70 | let prev_index = match self.selected() { 71 | Some(i) => { 72 | if i == 0 { 73 | 0 74 | } else { 75 | i - 1 76 | } 77 | } 78 | None => 0, 79 | }; 80 | self.state.select(Some(prev_index)); 81 | } 82 | 83 | pub fn get_items(&mut self) -> &mut Vec { 84 | &mut self.items 85 | } 86 | 87 | pub fn get_state(&mut self) -> &mut ListState { 88 | &mut self.state 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/brn_tui/tui_data.rs: -------------------------------------------------------------------------------- 1 | use crate::brn_tui::input_mode::InputMode; 2 | use crate::brn_tui::input_string::InputString; 3 | use crate::brn_tui::stateful_list::StatefulList; 4 | use crate::note_utility::NoteUtility; 5 | 6 | pub struct TuiData { 7 | pub note_list: StatefulList, 8 | pub note_content_preview: String, 9 | pub message: String, 10 | pub search_text: InputString, 11 | pub edit_text: InputString, 12 | pub input_mode: InputMode, 13 | pub note_name_cache: String, 14 | pub note_list_title: String, 15 | } 16 | 17 | impl Default for TuiData { 18 | fn default() -> TuiData { 19 | let mut tui_data = TuiData { 20 | note_list: StatefulList::with_items(NoteUtility::get(100)), 21 | note_content_preview: String::default(), 22 | message: String::default(), 23 | search_text: InputString::from("/"), 24 | edit_text: InputString::from("Name: "), 25 | input_mode: InputMode::Normal, 26 | note_name_cache: String::default(), 27 | note_list_title: String::from("List"), 28 | }; 29 | tui_data.note_list.select(Some(0)); 30 | return tui_data; 31 | } 32 | } 33 | 34 | impl TuiData {} 35 | -------------------------------------------------------------------------------- /src/collection_tool.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashSet; 2 | use std::hash::Hash; 3 | 4 | pub struct CollectionTool; 5 | impl CollectionTool { 6 | pub fn intersect(a: &mut HashSet, b: &mut HashSet) -> HashSet 7 | where 8 | T: Hash, 9 | T: Eq, 10 | { 11 | let intersected_set: HashSet = a.iter().filter_map(|v| b.take(v)).collect(); 12 | return intersected_set; 13 | } 14 | 15 | // pub fn difference(a: &mut HashSet, b: &mut HashSet) -> HashSet 16 | // where 17 | // T: Hash 18 | // T: Eq, 19 | // { 20 | // let resulting_set: HashSet = a.iter().filter_map(|v| 21 | // if b.contains(v) { 22 | // None 23 | // } else { 24 | // Some(v) 25 | // }).collect(); 26 | // let mut resulting_set = HashSet::new(); 27 | // let mut referencing_set = HashSet::new(); 28 | 29 | // for value in a.iter() { 30 | // if !b.contains(value) { 31 | // referencing_set.insert(value); 32 | // } 33 | // } 34 | 35 | // for reference_value in referencing_set.iter() { 36 | // if let Some(taken_value) = a.take(reference_value.cloned()) { 37 | // resulting_set.insert(taken_value); 38 | // } 39 | // } 40 | 41 | // return resulting_set; 42 | // } 43 | } 44 | -------------------------------------------------------------------------------- /src/directory.rs: -------------------------------------------------------------------------------- 1 | use crate::message::Message; 2 | use std::ffi::OsStr; 3 | use std::path::Path; 4 | 5 | pub struct Directory; 6 | impl Directory { 7 | pub fn is_zettelkasten_dir(directory: &OsStr, hide_error_messages: bool) -> bool { 8 | if Path::new(directory).join(".zettelkasten").exists() { 9 | return true; 10 | } else { 11 | if !hide_error_messages { 12 | Message::error(&format!( 13 | "the specified path is not zettelkasten directory: '{}'", 14 | directory.to_string_lossy() 15 | )); 16 | Message::hint("use the 'init' subcommand to initialize a zettelkasten directory"); 17 | } 18 | return false; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/file_utility.rs: -------------------------------------------------------------------------------- 1 | use std::fs::File; 2 | use std::io::{Error, Read}; 3 | use std::path::Path; 4 | 5 | pub struct FileUtility; 6 | 7 | impl FileUtility { 8 | pub fn get_content_from_file>(path: P) -> Result { 9 | let mut file = match File::open(path) { 10 | Ok(opened_file) => opened_file, 11 | Err(error) => return Err(error), 12 | }; 13 | let mut file_content = String::new(); 14 | 15 | match file.read_to_string(&mut file_content) { 16 | Ok(_) => {} 17 | Err(error) => return Err(error), 18 | }; 19 | 20 | return Ok(file_content); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/.browserslist: -------------------------------------------------------------------------------- 1 | ie 9-11 2 | firefox >= 4 3 | chrome >= 23 4 | > 1% 5 | node >= 0.10 6 | last 2 major versions 7 | since 2012 8 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "commonjs": true, 4 | "shared-node-browser": true, 5 | "node": true, 6 | "mocha": true 7 | }, 8 | "parserOptions": { 9 | "sourceType": "module", 10 | "ecmaVersion": 6 11 | }, 12 | "extends": "eslint:recommended", 13 | "rules": { 14 | "no-redeclare": "off", 15 | "semi": "error", 16 | "no-unused-vars": [ 17 | "error", 18 | { 19 | "vars": "all", 20 | "args": "none" 21 | } 22 | ] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | **Issue type** 6 | 7 | 17 | 18 | 19 | Bug report 20 | Feature request 21 | 22 | 23 | 24 | 25 | 26 | 27 | **Environment info** 28 | 29 | - Cytoscape.js version : 30 | - Browser/Node.js & version : 31 | 32 | **Current (buggy) behaviour** 33 | 34 | 35 | 36 | 37 | **Desired behaviour** 38 | 39 | 40 | 41 | 42 | **Minimum steps to reproduce** 43 | 44 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | **Description of new feature** 65 | 66 | 67 | 68 | 69 | **Motivation for new feature** 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Before you post** 11 | 12 | A request for help or a requests for a how-to should be directed to Stack Overflow: 13 | http://stackoverflow.com/questions/tagged/cytoscape.js 14 | 15 | 16 | 17 | **Environment info** 18 | 19 | - Cytoscape.js version : 20 | - Browser/Node.js & version : 21 | 22 | 23 | 24 | **Current (buggy) behaviour** 25 | 26 | _What does the bug do?_ 27 | 28 | 29 | 30 | **Desired behaviour** 31 | 32 | _What do you expect Cytoscape.js to do instead?_ 33 | 34 | 35 | 36 | **Minimum steps to reproduce** 37 | 38 | _What do you need to do to reproduce the issue?_ 39 | 40 | _Fork/clone this JSBin demo and reproduce your issue so that your issue can be addressed quickly and effectively:_ 41 | http://jsbin.com/fiqugiq 42 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Description of new feature** 11 | 12 | _What should the new feature do? For visual features, include an image/mockup of the expected output._ 13 | 14 | 15 | 16 | **Motivation for new feature** 17 | 18 | _Describe your use case for this new feature._ 19 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | **Issue type** 6 | 7 | 14 | 15 | 16 | Bug report 17 | Feature request 18 | 19 | 20 | 21 | 22 | 23 | 24 | **Environment info** 25 | 26 | - Cytoscape.js version : 27 | - Browser/Node.js & version : 28 | 29 | **Current (buggy) behaviour** 30 | 31 | 32 | 33 | 34 | **Desired behaviour** 35 | 36 | 37 | 38 | 39 | **Minimum steps to reproduce** 40 | 41 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | **Description of new feature** 62 | 63 | 64 | 65 | 66 | **Motivation for new feature** 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 14 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | # Label to use when marking an issue as stale 9 | staleLabel: stale 10 | # Comment to post when marking an issue as stale. Set to `false` to disable 11 | markComment: > 12 | This issue has been automatically marked as stale, because it has not had 13 | activity within the past 14 days. It will be closed if no further activity 14 | occurs within the next 7 days. If a feature request is important to you, 15 | please consider making a pull request. Thank you for your contributions. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: false 18 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Automated tests 2 | on: 3 | push: 4 | paths: 5 | - 'src/**' 6 | - 'package.json' 7 | - 'package-lock.json' 8 | - '.babelrc' 9 | - '.eslintrc.json' 10 | - '.github/workflows/tests.yaml' 11 | - 'rollup.config.js' 12 | 13 | jobs: 14 | ci: 15 | runs-on: ubuntu-latest 16 | container: node:16 17 | 18 | steps: 19 | - name: Check out repository code 20 | uses: actions/checkout@v2 21 | 22 | - name: Install dependencies 23 | run: npm install 24 | 25 | - name: Run tests 26 | run: npm test 27 | 28 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/.size-snapshot.json: -------------------------------------------------------------------------------- 1 | { 2 | "build/cytoscape.umd.js": { 3 | "bundled": 1022479, 4 | "minified": 365247, 5 | "gzipped": 112541 6 | }, 7 | "build/cytoscape.cjs.js": { 8 | "bundled": 871807, 9 | "minified": 371579, 10 | "gzipped": 111901 11 | }, 12 | "build/cytoscape.esm.js": { 13 | "bundled": 871574, 14 | "minified": 371391, 15 | "gzipped": 111859, 16 | "treeshaked": { 17 | "rollup": { 18 | "code": 346726, 19 | "import_statements": 132 20 | }, 21 | "webpack": { 22 | "code": 348238 23 | } 24 | } 25 | }, 26 | "build/cytoscape.esm.min.js": { 27 | "bundled": 365052, 28 | "minified": 364527, 29 | "gzipped": 112365, 30 | "treeshaked": { 31 | "rollup": { 32 | "code": 363990, 33 | "import_statements": 0 34 | }, 35 | "webpack": { 36 | "code": 365278 37 | } 38 | } 39 | }, 40 | "build\\cytoscape.umd.js": { 41 | "bundled": 942118, 42 | "minified": 351104, 43 | "gzipped": 109191 44 | }, 45 | "build\\cytoscape.esm.min.js": { 46 | "bundled": 350909, 47 | "minified": 350411, 48 | "gzipped": 109012, 49 | "treeshaked": { 50 | "rollup": { 51 | "code": 349903, 52 | "import_statements": 0 53 | }, 54 | "webpack": { 55 | "code": 351193 56 | } 57 | } 58 | }, 59 | "build\\cytoscape.cjs.js": { 60 | "bundled": 868703, 61 | "minified": 370553, 62 | "gzipped": 111528 63 | }, 64 | "build\\cytoscape.esm.js": { 65 | "bundled": 868530, 66 | "minified": 370410, 67 | "gzipped": 111491, 68 | "treeshaked": { 69 | "rollup": { 70 | "code": 345754, 71 | "import_statements": 51 72 | }, 73 | "webpack": { 74 | "code": 347140 75 | } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "10" 4 | - "12" 5 | sudo: false 6 | script: npm run travis 7 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016-2022, The Cytoscape Consortium. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the “Software”), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | Please report security issues to maxkfranz@gmail.com. Thank you. 6 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/license-update.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | 4 | const year = (new Date()).getFullYear(); 5 | 6 | const license = `Copyright (c) 2016-${year}, The Cytoscape Consortium. 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy of 9 | this software and associated documentation files (the “Software”), to deal in 10 | the Software without restriction, including without limitation the rights to 11 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | of the Software, and to permit persons to whom the Software is furnished to do 13 | so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE.`; 25 | 26 | fs.writeFileSync(path.join(__dirname, 'LICENSE'), license); 27 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/rollup.config.js: -------------------------------------------------------------------------------- 1 | import nodeResolve from '@rollup/plugin-node-resolve'; 2 | import commonjs from '@rollup/plugin-commonjs'; 3 | import babel from '@rollup/plugin-babel'; 4 | import replace from '@rollup/plugin-replace'; 5 | import { terser } from "rollup-plugin-terser"; 6 | import { sizeSnapshot } from 'rollup-plugin-size-snapshot'; 7 | import license from 'rollup-plugin-license'; 8 | import path from 'path'; 9 | 10 | const VERSION = process.env.VERSION || 'snapshot'; // default snapshot 11 | const FILE = process.env.FILE; 12 | const SOURCEMAPS = process.env.SOURCEMAPS === 'true'; // default false 13 | const BABEL = process.env.BABEL !== 'false'; // default true 14 | const NODE_ENV = process.env.NODE_ENV === 'development' ? 'development' : 'production'; // default prod 15 | const matchSnapshot = process.env.SNAPSHOT === 'match'; 16 | 17 | const input = './src/index.js'; 18 | 19 | const name = 'cytoscape'; 20 | 21 | const envVariables = { 22 | 'process.env.VERSION': JSON.stringify(VERSION), 23 | 'process.env.NODE_ENV': JSON.stringify(NODE_ENV) 24 | }; 25 | 26 | const getBabelOptions = () => ({ 27 | exclude: '**/node_modules/**' 28 | }); 29 | 30 | // Ignore all node_modules dependencies 31 | const isExternal = id => !id.startsWith('\0') && !id.startsWith('.') && !id.startsWith('/'); 32 | 33 | const licenseHeaderOptions = { 34 | sourcemap: true, 35 | banner: { 36 | content: { 37 | file: path.join(__dirname, 'LICENSE') 38 | } 39 | } 40 | }; 41 | 42 | const configs = [ 43 | { 44 | input, 45 | output: { 46 | file: 'build/cytoscape.umd.js', 47 | format: 'umd', 48 | name, 49 | sourcemap: SOURCEMAPS ? 'inline' : false 50 | }, 51 | plugins: [ 52 | nodeResolve(), 53 | commonjs({ include: '**/node_modules/**' }), 54 | BABEL ? babel(getBabelOptions()) : {}, 55 | replace(envVariables), 56 | license(licenseHeaderOptions), 57 | !FILE ? sizeSnapshot({ matchSnapshot }) : {} 58 | ] 59 | }, 60 | 61 | { 62 | input, 63 | output: { 64 | file: 'build/cytoscape.min.js', 65 | format: 'umd', 66 | name 67 | }, 68 | plugins: [ 69 | nodeResolve(), 70 | commonjs({ include: '**/node_modules/**' }), 71 | BABEL ? babel(getBabelOptions()) : {}, 72 | replace(envVariables), 73 | terser({ 74 | sourcemap: false 75 | }), 76 | license(licenseHeaderOptions) 77 | ] 78 | }, 79 | 80 | { 81 | input, 82 | output: { 83 | file: 'build/cytoscape.esm.min.js', 84 | format: 'es' 85 | }, 86 | plugins: [ 87 | nodeResolve(), 88 | commonjs({ include: '**/node_modules/**' }), 89 | BABEL ? babel(getBabelOptions()) : {}, 90 | replace(envVariables), 91 | license(licenseHeaderOptions), 92 | terser(), 93 | !FILE ? sizeSnapshot({ matchSnapshot }) : {} 94 | ] 95 | }, 96 | 97 | { 98 | input, 99 | output: { file: 'build/cytoscape.cjs.js', format: 'cjs' }, 100 | external: isExternal, 101 | plugins: [ 102 | nodeResolve(), 103 | BABEL ? babel(getBabelOptions()) : {}, 104 | replace(envVariables), 105 | license(licenseHeaderOptions), 106 | !FILE ? sizeSnapshot({ matchSnapshot }) : {} 107 | ] 108 | }, 109 | 110 | { 111 | input, 112 | output: { file: 'build/cytoscape.esm.js', format: 'es' }, 113 | external: isExternal, 114 | plugins: [ 115 | nodeResolve(), 116 | BABEL ? babel(getBabelOptions()) : {}, 117 | replace(envVariables), 118 | license(licenseHeaderOptions), 119 | !FILE ? sizeSnapshot({ matchSnapshot }) : {} 120 | ] 121 | } 122 | ]; 123 | 124 | export default FILE 125 | ? configs.filter(config => config.output.file.endsWith(FILE + '.js')) 126 | : configs; 127 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/cjs.js: -------------------------------------------------------------------------------- 1 | // an entrypoint to use the raw source in cjs projects 2 | // e.g. require('cytoscape/src/cjs') or setting an alias in your build tool of 'cytoscape':'cytoscape/src/cjs' 3 | 4 | module.exports = require('./index.js').default; 5 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/algorithms/bfs-dfs.js: -------------------------------------------------------------------------------- 1 | import * as is from '../../is'; 2 | 3 | let defineSearch = function( params ){ 4 | params = { 5 | bfs: params.bfs || !params.dfs, 6 | dfs: params.dfs || !params.bfs 7 | }; 8 | 9 | // from pseudocode on wikipedia 10 | return function searchFn( roots, fn, directed ){ 11 | let options; 12 | if( is.plainObject( roots ) && !is.elementOrCollection( roots ) ){ 13 | options = roots; 14 | roots = options.roots || options.root; 15 | fn = options.visit; 16 | directed = options.directed; 17 | } 18 | 19 | directed = arguments.length === 2 && !is.fn( fn ) ? fn : directed; 20 | fn = is.fn( fn ) ? fn : function(){}; 21 | 22 | let cy = this._private.cy; 23 | let v = roots = is.string( roots ) ? this.filter( roots ) : roots; 24 | let Q = []; 25 | let connectedNodes = []; 26 | let connectedBy = {}; 27 | let id2depth = {}; 28 | let V = {}; 29 | let j = 0; 30 | let found; 31 | let { nodes, edges } = this.byGroup(); 32 | 33 | // enqueue v 34 | for( let i = 0; i < v.length; i++ ){ 35 | let vi = v[i]; 36 | let viId = vi.id(); 37 | 38 | if( vi.isNode() ){ 39 | Q.unshift( vi ); 40 | 41 | if( params.bfs ){ 42 | V[ viId ] = true; 43 | 44 | connectedNodes.push( vi ); 45 | } 46 | 47 | id2depth[ viId ] = 0; 48 | } 49 | } 50 | 51 | while( Q.length !== 0 ){ 52 | let v = params.bfs ? Q.shift() : Q.pop(); 53 | let vId = v.id(); 54 | 55 | if( params.dfs ){ 56 | if( V[ vId ] ){ continue; } 57 | 58 | V[ vId ] = true; 59 | 60 | connectedNodes.push( v ); 61 | } 62 | 63 | let depth = id2depth[ vId ]; 64 | let prevEdge = connectedBy[ vId ]; 65 | let src = prevEdge != null ? prevEdge.source() : null; 66 | let tgt = prevEdge != null ? prevEdge.target() : null; 67 | let prevNode = prevEdge == null ? undefined : ( v.same(src) ? tgt[0] : src[0] ); 68 | let ret; 69 | 70 | ret = fn( v, prevEdge, prevNode, j++, depth ); 71 | 72 | if( ret === true ){ 73 | found = v; 74 | break; 75 | } 76 | 77 | if( ret === false ){ 78 | break; 79 | } 80 | 81 | let vwEdges = v.connectedEdges().filter(e => (!directed || e.source().same(v)) && edges.has(e)); 82 | for( let i = 0; i < vwEdges.length; i++ ){ 83 | let e = vwEdges[ i ]; 84 | let w = e.connectedNodes().filter(n => !n.same(v) && nodes.has(n)); 85 | let wId = w.id(); 86 | 87 | if( w.length !== 0 && !V[ wId ] ){ 88 | w = w[0]; 89 | 90 | Q.push( w ); 91 | 92 | if( params.bfs ){ 93 | V[ wId ] = true; 94 | 95 | connectedNodes.push( w ); 96 | } 97 | 98 | connectedBy[ wId ] = e; 99 | 100 | id2depth[ wId ] = id2depth[ vId ] + 1; 101 | } 102 | } 103 | 104 | } 105 | 106 | let connectedEles = cy.collection(); 107 | 108 | for( let i = 0; i < connectedNodes.length; i++ ){ 109 | let node = connectedNodes[ i ]; 110 | let edge = connectedBy[ node.id() ]; 111 | 112 | if( edge != null ){ 113 | connectedEles.push( edge ); 114 | } 115 | 116 | connectedEles.push( node ); 117 | } 118 | 119 | return { 120 | path: cy.collection( connectedEles ), 121 | found: cy.collection( found ) 122 | }; 123 | }; 124 | }; 125 | 126 | // search, spanning trees, etc 127 | let elesfn = ({ 128 | breadthFirstSearch: defineSearch( { bfs: true } ), 129 | depthFirstSearch: defineSearch( { dfs: true } ) 130 | }); 131 | 132 | // nice, short mathemathical alias 133 | elesfn.bfs = elesfn.breadthFirstSearch; 134 | elesfn.dfs = elesfn.depthFirstSearch; 135 | 136 | export default elesfn; 137 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/algorithms/closeness-centrality.js: -------------------------------------------------------------------------------- 1 | import * as is from '../../is'; 2 | import * as util from '../../util'; 3 | 4 | const defaults = util.defaults({ 5 | harmonic: true, 6 | weight: () => 1, 7 | directed: false, 8 | root: null 9 | }); 10 | 11 | const elesfn = ({ 12 | 13 | closenessCentralityNormalized: function( options ){ 14 | let { harmonic, weight, directed } = defaults(options); 15 | 16 | let cy = this.cy(); 17 | let closenesses = {}; 18 | let maxCloseness = 0; 19 | let nodes = this.nodes(); 20 | let fw = this.floydWarshall({ weight, directed }); 21 | 22 | // Compute closeness for every node and find the maximum closeness 23 | for( let i = 0; i < nodes.length; i++ ){ 24 | let currCloseness = 0; 25 | let node_i = nodes[i]; 26 | 27 | for( let j = 0; j < nodes.length; j++ ){ 28 | if( i !== j ){ 29 | let d = fw.distance( node_i, nodes[j] ); 30 | 31 | if( harmonic ){ 32 | currCloseness += 1 / d; 33 | } else { 34 | currCloseness += d; 35 | } 36 | } 37 | } 38 | 39 | if( !harmonic ){ 40 | currCloseness = 1 / currCloseness; 41 | } 42 | 43 | if( maxCloseness < currCloseness ){ 44 | maxCloseness = currCloseness; 45 | } 46 | 47 | closenesses[ node_i.id() ] = currCloseness; 48 | } 49 | 50 | return { 51 | closeness: function( node ){ 52 | if( maxCloseness == 0 ){ return 0; } 53 | 54 | if( is.string( node ) ){ 55 | // from is a selector string 56 | node = (cy.filter( node )[0]).id(); 57 | } else { 58 | // from is a node 59 | node = node.id(); 60 | } 61 | 62 | return closenesses[ node ] / maxCloseness; 63 | } 64 | }; 65 | }, 66 | 67 | // Implemented from pseudocode from wikipedia 68 | closenessCentrality: function( options ){ 69 | let { root, weight, directed, harmonic } = defaults(options); 70 | 71 | root = this.filter(root)[0]; 72 | 73 | // we need distance from this node to every other node 74 | let dijkstra = this.dijkstra({ root, weight, directed }); 75 | let totalDistance = 0; 76 | let nodes = this.nodes(); 77 | 78 | for( let i = 0; i < nodes.length; i++ ){ 79 | let n = nodes[i]; 80 | 81 | if( !n.same(root) ){ 82 | let d = dijkstra.distanceTo(n); 83 | 84 | if( harmonic ){ 85 | totalDistance += 1 / d; 86 | } else { 87 | totalDistance += d; 88 | } 89 | } 90 | } 91 | 92 | return harmonic ? totalDistance : 1 / totalDistance; 93 | } // closenessCentrality 94 | 95 | }); // elesfn 96 | 97 | // nice, short mathemathical alias 98 | elesfn.cc = elesfn.closenessCentrality; 99 | elesfn.ccn = elesfn.closenessCentralityNormalised = elesfn.closenessCentralityNormalized; 100 | 101 | export default elesfn; 102 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/algorithms/clustering-distances.js: -------------------------------------------------------------------------------- 1 | // Common distance metrics for clustering algorithms 2 | // https://en.wikipedia.org/wiki/Hierarchical_clustering#Metric 3 | 4 | import * as is from '../../is'; 5 | 6 | let identity = x => x; 7 | let absDiff = ( p, q ) => Math.abs( q - p ); 8 | let addAbsDiff = ( total, p, q ) => total + absDiff(p, q); 9 | let addSquaredDiff = ( total, p, q ) => total + Math.pow( q - p, 2 ); 10 | let sqrt = x => Math.sqrt(x); 11 | let maxAbsDiff = ( currentMax, p, q ) => Math.max( currentMax, absDiff(p, q) ); 12 | 13 | let getDistance = function( length, getP, getQ, init, visit, post = identity ){ 14 | let ret = init; 15 | let p, q; 16 | 17 | for ( let dim = 0; dim < length; dim++ ) { 18 | p = getP(dim); 19 | q = getQ(dim); 20 | 21 | ret = visit( ret, p, q ); 22 | } 23 | 24 | return post( ret ); 25 | }; 26 | 27 | let distances = { 28 | euclidean: function ( length, getP, getQ ) { 29 | if( length >= 2 ){ 30 | return getDistance( length, getP, getQ, 0, addSquaredDiff, sqrt ); 31 | } else { // for single attr case, more efficient to avoid sqrt 32 | return getDistance( length, getP, getQ, 0, addAbsDiff ); 33 | } 34 | }, 35 | squaredEuclidean: function ( length, getP, getQ ) { 36 | return getDistance( length, getP, getQ, 0, addSquaredDiff ); 37 | }, 38 | manhattan: function ( length, getP, getQ ) { 39 | return getDistance( length, getP, getQ, 0, addAbsDiff ); 40 | }, 41 | max: function ( length, getP, getQ ) { 42 | return getDistance( length, getP, getQ, -Infinity, maxAbsDiff ); 43 | } 44 | }; 45 | 46 | // in case the user accidentally doesn't use camel case 47 | distances['squared-euclidean'] = distances['squaredEuclidean']; 48 | distances['squaredeuclidean'] = distances['squaredEuclidean']; 49 | 50 | export default function( method, length, getP, getQ, nodeP, nodeQ ){ 51 | let impl; 52 | 53 | if( is.fn( method ) ){ 54 | impl = method; 55 | } else { 56 | impl = distances[ method ] || distances.euclidean; 57 | } 58 | 59 | if( length === 0 && is.fn( method ) ){ 60 | return impl( nodeP, nodeQ ); 61 | } else { 62 | return impl( length, getP, getQ, nodeP, nodeQ ); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/algorithms/dijkstra.js: -------------------------------------------------------------------------------- 1 | import * as is from '../../is'; 2 | import Heap from '../../heap'; 3 | import { defaults } from '../../util'; 4 | 5 | const dijkstraDefaults = defaults({ 6 | root: null, 7 | weight: edge => 1, 8 | directed: false 9 | }); 10 | 11 | let elesfn = ({ 12 | 13 | dijkstra: function( options ){ 14 | if( !is.plainObject(options) ){ 15 | let args = arguments; 16 | 17 | options = { root: args[0], weight: args[1], directed: args[2] }; 18 | } 19 | 20 | let { root, weight, directed } = dijkstraDefaults(options); 21 | 22 | let eles = this; 23 | let weightFn = weight; 24 | let source = is.string( root ) ? this.filter( root )[0] : root[0]; 25 | let dist = {}; 26 | let prev = {}; 27 | let knownDist = {}; 28 | 29 | let { nodes, edges } = this.byGroup(); 30 | edges.unmergeBy( ele => ele.isLoop() ); 31 | 32 | let getDist = node => dist[ node.id() ]; 33 | 34 | let setDist = ( node, d ) => { 35 | dist[ node.id() ] = d; 36 | 37 | Q.updateItem( node ); 38 | }; 39 | 40 | let Q = new Heap( (a, b) => getDist(a) - getDist(b) ); 41 | 42 | for( let i = 0; i < nodes.length; i++ ){ 43 | let node = nodes[ i ]; 44 | 45 | dist[ node.id() ] = node.same( source ) ? 0 : Infinity; 46 | Q.push( node ); 47 | } 48 | 49 | let distBetween = ( u, v ) => { 50 | let uvs = ( directed ? u.edgesTo(v) : u.edgesWith(v) ).intersect( edges ); 51 | let smallestDistance = Infinity; 52 | let smallestEdge; 53 | 54 | for( let i = 0; i < uvs.length; i++ ){ 55 | let edge = uvs[ i ]; 56 | let weight = weightFn( edge ); 57 | 58 | if( weight < smallestDistance || !smallestEdge ){ 59 | smallestDistance = weight; 60 | smallestEdge = edge; 61 | } 62 | } 63 | 64 | return { 65 | edge: smallestEdge, 66 | dist: smallestDistance 67 | }; 68 | }; 69 | 70 | while( Q.size() > 0 ){ 71 | let u = Q.pop(); 72 | let smalletsDist = getDist( u ); 73 | let uid = u.id(); 74 | 75 | knownDist[ uid ] = smalletsDist; 76 | 77 | if( smalletsDist === Infinity ){ 78 | continue; 79 | } 80 | 81 | let neighbors = u.neighborhood().intersect( nodes ); 82 | for( let i = 0; i < neighbors.length; i++ ){ 83 | let v = neighbors[ i ]; 84 | let vid = v.id(); 85 | let vDist = distBetween( u, v ); 86 | 87 | let alt = smalletsDist + vDist.dist; 88 | 89 | if( alt < getDist( v ) ){ 90 | setDist( v, alt ); 91 | 92 | prev[ vid ] = { 93 | node: u, 94 | edge: vDist.edge 95 | }; 96 | } 97 | } // for 98 | } // while 99 | 100 | return { 101 | distanceTo: function( node ){ 102 | let target = is.string( node ) ? nodes.filter( node )[0] : node[0]; 103 | 104 | return knownDist[ target.id() ]; 105 | }, 106 | 107 | pathTo: function( node ){ 108 | let target = is.string( node ) ? nodes.filter( node )[0] : node[0]; 109 | let S = []; 110 | let u = target; 111 | let uid = u.id(); 112 | 113 | if( target.length > 0 ){ 114 | S.unshift( target ); 115 | 116 | while( prev[ uid ] ){ 117 | let p = prev[ uid ]; 118 | 119 | S.unshift( p.edge ); 120 | S.unshift( p.node ); 121 | 122 | u = p.node; 123 | uid = u.id(); 124 | } 125 | } 126 | 127 | return eles.spawn( S ); 128 | } 129 | }; 130 | } 131 | }); 132 | 133 | export default elesfn; 134 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/algorithms/floyd-warshall.js: -------------------------------------------------------------------------------- 1 | import * as is from '../../is'; 2 | import { defaults } from '../../util'; 3 | 4 | const floydWarshallDefaults = defaults({ 5 | weight: edge => 1, 6 | directed: false 7 | }); 8 | 9 | let elesfn = ({ 10 | 11 | // Implemented from pseudocode from wikipedia 12 | floydWarshall: function( options ){ 13 | let cy = this.cy(); 14 | 15 | let { weight, directed } = floydWarshallDefaults(options); 16 | let weightFn = weight; 17 | 18 | let { nodes, edges } = this.byGroup(); 19 | 20 | let N = nodes.length; 21 | let Nsq = N * N; 22 | 23 | let indexOf = node => nodes.indexOf(node); 24 | let atIndex = i => nodes[i]; 25 | 26 | // Initialize distance matrix 27 | let dist = new Array(Nsq); 28 | for( let n = 0; n < Nsq; n++ ){ 29 | let j = n % N; 30 | let i = (n - j) / N; 31 | 32 | if( i === j ){ 33 | dist[n] = 0; 34 | } else { 35 | dist[n] = Infinity; 36 | } 37 | } 38 | 39 | // Initialize matrix used for path reconstruction 40 | // Initialize distance matrix 41 | let next = new Array(Nsq); 42 | let edgeNext = new Array(Nsq); 43 | 44 | // Process edges 45 | for( let i = 0; i < edges.length; i++ ){ 46 | let edge = edges[i]; 47 | let src = edge.source()[0]; 48 | let tgt = edge.target()[0]; 49 | 50 | if( src === tgt ){ continue; } // exclude loops 51 | 52 | let s = indexOf( src ); 53 | let t = indexOf( tgt ); 54 | let st = s * N + t; // source to target index 55 | let weight = weightFn( edge ); 56 | 57 | // Check if already process another edge between same 2 nodes 58 | if( dist[st] > weight ){ 59 | dist[st] = weight; 60 | next[st] = t; 61 | edgeNext[st] = edge; 62 | } 63 | 64 | // If undirected graph, process 'reversed' edge 65 | if( !directed ){ 66 | let ts = t * N + s; // target to source index 67 | 68 | if( !directed && dist[ts] > weight ){ 69 | dist[ts] = weight; 70 | next[ts] = s; 71 | edgeNext[ts] = edge; 72 | } 73 | } 74 | } 75 | 76 | // Main loop 77 | for( let k = 0; k < N; k++ ){ 78 | 79 | for( let i = 0; i < N; i++ ){ 80 | let ik = i * N + k; 81 | 82 | for( let j = 0; j < N; j++ ){ 83 | let ij = i * N + j; 84 | let kj = k * N + j; 85 | 86 | if( dist[ik] + dist[kj] < dist[ij] ){ 87 | dist[ij] = dist[ik] + dist[kj]; 88 | next[ij] = next[ik]; 89 | } 90 | } 91 | } 92 | } 93 | 94 | let getArgEle = ele => ( is.string(ele) ? cy.filter(ele) : ele )[0]; 95 | let indexOfArgEle = ele => indexOf(getArgEle(ele)); 96 | 97 | let res = { 98 | distance: function( from, to ){ 99 | let i = indexOfArgEle(from); 100 | let j = indexOfArgEle(to); 101 | 102 | return dist[ i * N + j ]; 103 | }, 104 | 105 | path: function( from, to ){ 106 | let i = indexOfArgEle(from); 107 | let j = indexOfArgEle(to); 108 | 109 | let fromNode = atIndex(i); 110 | 111 | if( i === j ){ return fromNode.collection(); } 112 | 113 | if( next[i * N + j] == null ){ return cy.collection(); } 114 | 115 | let path = cy.collection(); 116 | let prev = i; 117 | let edge; 118 | 119 | path.merge( fromNode ); 120 | 121 | while( i !== j ){ 122 | prev = i; 123 | i = next[i * N + j]; 124 | edge = edgeNext[prev * N + i]; 125 | 126 | path.merge( edge ); 127 | path.merge( atIndex(i) ); 128 | } 129 | 130 | return path; 131 | } 132 | }; 133 | 134 | return res; 135 | 136 | } // floydWarshall 137 | 138 | }); // elesfn 139 | 140 | export default elesfn; 141 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/algorithms/hierholzer.js: -------------------------------------------------------------------------------- 1 | import * as is from '../../is'; 2 | import { defaults } from '../../util'; 3 | 4 | const hierholzerDefaults = defaults({ 5 | root: undefined, 6 | directed: false 7 | }); 8 | 9 | let elesfn = ({ 10 | hierholzer: function( options ){ 11 | if (!is.plainObject(options)) { 12 | let args = arguments; 13 | options = { root: args[0], directed: args[1] }; 14 | } 15 | let { root, directed } = hierholzerDefaults(options); 16 | let eles = this; 17 | let dflag = false; 18 | let oddIn; 19 | let oddOut; 20 | let startVertex; 21 | if (root) startVertex = is.string(root) ? this.filter(root)[0].id() : root[0].id(); 22 | let nodes = {}; 23 | let edges = {}; 24 | 25 | if (directed) { 26 | eles.forEach(function(ele){ 27 | let id = ele.id(); 28 | if(ele.isNode()) { 29 | let ind = ele.indegree(true); 30 | let outd = ele.outdegree(true); 31 | let d1 = ind - outd; 32 | let d2 = outd - ind; 33 | if (d1 == 1) { 34 | if (oddIn) dflag = true; 35 | else oddIn = id; 36 | } else if (d2 == 1) { 37 | if (oddOut) dflag = true; 38 | else oddOut = id; 39 | } else if ((d2 > 1) || (d1 > 1)) { 40 | dflag = true; 41 | } 42 | nodes[id] = []; 43 | ele.outgoers().forEach(e => { 44 | if (e.isEdge()) nodes[id].push(e.id()); 45 | }); 46 | } else { 47 | edges[id] = [undefined, ele.target().id()]; 48 | } 49 | }); 50 | } else { 51 | eles.forEach(function(ele){ 52 | let id = ele.id(); 53 | if(ele.isNode()) { 54 | let d = ele.degree(true); 55 | if (d%2) { 56 | if (!oddIn) oddIn = id; 57 | else if (!oddOut) oddOut = id; 58 | else dflag = true; 59 | } 60 | nodes[id] = []; 61 | ele.connectedEdges().forEach(e => nodes[id].push(e.id())); 62 | } else { 63 | edges[id] = [ele.source().id(), ele.target().id()]; 64 | } 65 | }); 66 | } 67 | 68 | let result = { 69 | found: false, 70 | trail: undefined 71 | }; 72 | 73 | if (dflag) return result; 74 | else if (oddOut && oddIn) { 75 | if (directed) { 76 | if (startVertex && (oddOut != startVertex)) { 77 | return result; 78 | } 79 | startVertex = oddOut; 80 | } else { 81 | if (startVertex && (oddOut != startVertex) && (oddIn != startVertex)) { 82 | return result; 83 | } else if (!startVertex) { 84 | startVertex = oddOut; 85 | } 86 | } 87 | } else { 88 | if (!startVertex) startVertex = eles[0].id(); 89 | } 90 | 91 | const walk = (v) => { 92 | let currentNode = v; 93 | let subtour = [v]; 94 | let adj, adjTail, adjHead; 95 | while (nodes[currentNode].length) { 96 | adj = nodes[currentNode].shift(); 97 | adjTail = edges[adj][0]; 98 | adjHead = edges[adj][1]; 99 | if (currentNode != adjHead) { 100 | nodes[adjHead] = nodes[adjHead].filter(e => e != adj); 101 | currentNode = adjHead; 102 | } else if (!directed && (currentNode != adjTail)) { 103 | nodes[adjTail] = nodes[adjTail].filter(e => e != adj); 104 | currentNode = adjTail; 105 | } 106 | subtour.unshift(adj); 107 | subtour.unshift(currentNode); 108 | } 109 | return subtour; 110 | }; 111 | 112 | let trail = []; 113 | let subtour = []; 114 | subtour = walk(startVertex); 115 | while (subtour.length != 1) { 116 | if (nodes[subtour[0]].length == 0) { 117 | trail.unshift(eles.getElementById(subtour.shift())); 118 | trail.unshift(eles.getElementById(subtour.shift())); 119 | } else { 120 | subtour = walk(subtour.shift()).concat(subtour); 121 | } 122 | } 123 | trail.unshift(eles.getElementById(subtour.shift())); // final node 124 | 125 | for (let d in nodes) { 126 | if (nodes[d].length) { 127 | return result; 128 | } 129 | } 130 | result.found = true; 131 | result.trail = this.spawn( trail, true ); 132 | return result; 133 | }, 134 | }); 135 | 136 | export default elesfn; 137 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/algorithms/hopcroft-tarjan-biconnected.js: -------------------------------------------------------------------------------- 1 | let hopcroftTarjanBiconnected = function() { 2 | let eles = this; 3 | let nodes = {}; 4 | let id = 0; 5 | let edgeCount = 0; 6 | let components = []; 7 | let stack = []; 8 | let visitedEdges = {}; 9 | 10 | const buildComponent = (x, y) => { 11 | let i = stack.length-1; 12 | let cutset = []; 13 | let component = eles.spawn(); 14 | 15 | while (stack[i].x != x || stack[i].y != y) { 16 | cutset.push(stack.pop().edge); 17 | i--; 18 | } 19 | cutset.push(stack.pop().edge); 20 | 21 | cutset.forEach(edge => { 22 | let connectedNodes = edge.connectedNodes() 23 | .intersection(eles); 24 | component.merge(edge); 25 | connectedNodes.forEach(node => { 26 | const nodeId = node.id(); 27 | const connectedEdges = node.connectedEdges() 28 | .intersection(eles); 29 | component.merge(node); 30 | if (!nodes[nodeId].cutVertex) { 31 | component.merge(connectedEdges); 32 | } else { 33 | component.merge(connectedEdges.filter(edge => edge.isLoop())); 34 | } 35 | }); 36 | }); 37 | components.push(component); 38 | }; 39 | 40 | const biconnectedSearch = (root, currentNode, parent) => { 41 | if (root === parent) edgeCount += 1; 42 | nodes[currentNode] = { 43 | id : id, 44 | low : id++, 45 | cutVertex : false 46 | }; 47 | let edges = eles.getElementById(currentNode) 48 | .connectedEdges() 49 | .intersection(eles); 50 | 51 | if (edges.size() === 0) { 52 | components.push(eles.spawn(eles.getElementById(currentNode))); 53 | } else { 54 | let sourceId, targetId, otherNodeId, edgeId; 55 | 56 | edges.forEach(edge => { 57 | sourceId = edge.source().id(); 58 | targetId = edge.target().id(); 59 | otherNodeId = (sourceId === currentNode) ? targetId : sourceId; 60 | 61 | if (otherNodeId !== parent) { 62 | edgeId = edge.id(); 63 | 64 | if (!visitedEdges[edgeId]) { 65 | visitedEdges[edgeId] = true; 66 | stack.push({ 67 | x : currentNode, 68 | y : otherNodeId, 69 | edge 70 | }); 71 | } 72 | 73 | if (!(otherNodeId in nodes)) { 74 | biconnectedSearch(root, otherNodeId, currentNode); 75 | nodes[currentNode].low = Math.min(nodes[currentNode].low, 76 | nodes[otherNodeId].low); 77 | 78 | if (nodes[currentNode].id <= nodes[otherNodeId].low) { 79 | nodes[currentNode].cutVertex = true; 80 | buildComponent(currentNode, otherNodeId); 81 | } 82 | } else { 83 | nodes[currentNode].low = Math.min(nodes[currentNode].low, 84 | nodes[otherNodeId].id); 85 | } 86 | } 87 | }); 88 | } 89 | }; 90 | 91 | eles.forEach(ele => { 92 | if (ele.isNode()) { 93 | let nodeId = ele.id(); 94 | 95 | if (!(nodeId in nodes)) { 96 | edgeCount = 0; 97 | biconnectedSearch(nodeId, nodeId); 98 | nodes[nodeId].cutVertex = (edgeCount > 1); 99 | } 100 | } 101 | }); 102 | 103 | let cutVertices = Object.keys(nodes) 104 | .filter(id => nodes[id].cutVertex) 105 | .map(id => eles.getElementById(id)); 106 | 107 | return { 108 | cut: eles.spawn(cutVertices), 109 | components 110 | }; 111 | }; 112 | 113 | export default { 114 | hopcroftTarjanBiconnected, 115 | htbc: hopcroftTarjanBiconnected, 116 | htb: hopcroftTarjanBiconnected, 117 | hopcroftTarjanBiconnectedComponents: hopcroftTarjanBiconnected 118 | }; 119 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/algorithms/index.js: -------------------------------------------------------------------------------- 1 | import * as util from '../../util'; 2 | import bfsDfs from './bfs-dfs'; 3 | import dijkstra from './dijkstra'; 4 | import kruskal from './kruskal'; 5 | import aStar from './a-star'; 6 | import floydWarshall from './floyd-warshall'; 7 | import bellmanFord from './bellman-ford'; 8 | import kargerStein from './karger-stein'; 9 | import pageRank from './page-rank'; 10 | import degreeCentrality from './degree-centrality'; 11 | import closenessCentrality from './closeness-centrality'; 12 | import betweennessCentrality from './betweenness-centrality'; 13 | import markovClustering from './markov-clustering'; 14 | import kClustering from './k-clustering'; 15 | import hierarchicalClustering from './hierarchical-clustering'; 16 | import affinityPropagation from './affinity-propagation'; 17 | import hierholzer from './hierholzer'; 18 | import hopcroftTarjanBiconnected from './hopcroft-tarjan-biconnected'; 19 | import tarjanStronglyConnected from './tarjan-strongly-connected'; 20 | 21 | var elesfn = {}; 22 | 23 | [ 24 | bfsDfs, 25 | dijkstra, 26 | kruskal, 27 | aStar, 28 | floydWarshall, 29 | bellmanFord, 30 | kargerStein, 31 | pageRank, 32 | degreeCentrality, 33 | closenessCentrality, 34 | betweennessCentrality, 35 | markovClustering, 36 | kClustering, 37 | hierarchicalClustering, 38 | affinityPropagation, 39 | hierholzer, 40 | hopcroftTarjanBiconnected, 41 | tarjanStronglyConnected 42 | ].forEach(function(props) { 43 | util.extend(elesfn, props); 44 | }); 45 | 46 | export default elesfn; 47 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/algorithms/kruskal.js: -------------------------------------------------------------------------------- 1 | let elesfn = ({ 2 | 3 | // kruskal's algorithm (finds min spanning tree, assuming undirected graph) 4 | // implemented from pseudocode from wikipedia 5 | kruskal: function( weightFn ){ 6 | weightFn = weightFn || ( edge => 1 ); 7 | 8 | let { nodes, edges } = this.byGroup(); 9 | let numNodes = nodes.length; 10 | let forest = new Array(numNodes); 11 | let A = nodes; // assumes byGroup() creates new collections that can be safely mutated 12 | 13 | let findSetIndex = ele => { 14 | for( let i = 0; i < forest.length; i++ ){ 15 | let eles = forest[i]; 16 | 17 | if( eles.has(ele) ){ return i; } 18 | } 19 | }; 20 | 21 | // start with one forest per node 22 | for( let i = 0; i < numNodes; i++ ){ 23 | forest[i] = this.spawn( nodes[i] ); 24 | } 25 | 26 | let S = edges.sort( (a, b) => weightFn(a) - weightFn(b) ); 27 | 28 | for( let i = 0; i < S.length; i++ ){ 29 | let edge = S[i]; 30 | let u = edge.source()[0]; 31 | let v = edge.target()[0]; 32 | let setUIndex = findSetIndex(u); 33 | let setVIndex = findSetIndex(v); 34 | let setU = forest[ setUIndex ]; 35 | let setV = forest[ setVIndex ]; 36 | 37 | if( setUIndex !== setVIndex ){ 38 | A.merge( edge ); 39 | 40 | // combine forests for u and v 41 | setU.merge( setV ); 42 | forest.splice( setVIndex, 1 ); 43 | } 44 | } 45 | 46 | return A; 47 | } 48 | }); 49 | 50 | export default elesfn; 51 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/algorithms/page-rank.js: -------------------------------------------------------------------------------- 1 | import { defaults } from '../../util'; 2 | import { inPlaceSumNormalize } from '../../math'; 3 | 4 | const pageRankDefaults = defaults({ 5 | dampingFactor: 0.8, 6 | precision: 0.000001, 7 | iterations: 200, 8 | weight: edge => 1 9 | }); 10 | 11 | let elesfn = ({ 12 | 13 | pageRank: function( options ){ 14 | let { dampingFactor, precision, iterations, weight } = pageRankDefaults(options); 15 | let cy = this._private.cy; 16 | let { nodes, edges } = this.byGroup(); 17 | let numNodes = nodes.length; 18 | let numNodesSqd = numNodes * numNodes; 19 | let numEdges = edges.length; 20 | 21 | // Construct transposed adjacency matrix 22 | // First lets have a zeroed matrix of the right size 23 | // We'll also keep track of the sum of each column 24 | let matrix = new Array(numNodesSqd); 25 | let columnSum = new Array(numNodes); 26 | let additionalProb = (1 - dampingFactor) / numNodes; 27 | 28 | // Create null matrix 29 | for( let i = 0; i < numNodes; i++ ){ 30 | for( let j = 0; j < numNodes; j++ ){ 31 | let n = i * numNodes + j; 32 | 33 | matrix[n] = 0; 34 | } 35 | 36 | columnSum[i] = 0; 37 | } 38 | 39 | // Now, process edges 40 | for( let i = 0; i < numEdges; i++ ){ 41 | let edge = edges[ i ]; 42 | let srcId = edge.data('source'); 43 | let tgtId = edge.data('target'); 44 | 45 | // Don't include loops in the matrix 46 | if( srcId === tgtId ){ continue; } 47 | 48 | let s = nodes.indexOfId( srcId ); 49 | let t = nodes.indexOfId( tgtId ); 50 | let w = weight( edge ); 51 | let n = t * numNodes + s; 52 | 53 | // Update matrix 54 | matrix[n] += w; 55 | 56 | // Update column sum 57 | columnSum[s] += w; 58 | } 59 | 60 | // Add additional probability based on damping factor 61 | // Also, take into account columns that have sum = 0 62 | let p = 1.0 / numNodes + additionalProb; // Shorthand 63 | 64 | // Traverse matrix, column by column 65 | for( let j = 0; j < numNodes; j++ ){ 66 | if( columnSum[j] === 0 ){ 67 | // No 'links' out from node jth, assume equal probability for each possible node 68 | for( let i = 0; i < numNodes; i++ ){ 69 | let n = i * numNodes + j; 70 | matrix[n] = p; 71 | } 72 | } else { 73 | // Node jth has outgoing link, compute normalized probabilities 74 | for( let i = 0; i < numNodes; i++ ){ 75 | let n = i * numNodes + j; 76 | 77 | matrix[n] = matrix[n] / columnSum[j] + additionalProb; 78 | } 79 | } 80 | } 81 | 82 | // Compute dominant eigenvector using power method 83 | let eigenvector = new Array(numNodes); 84 | let temp = new Array(numNodes); 85 | let previous; 86 | 87 | // Start with a vector of all 1's 88 | // Also, initialize a null vector which will be used as shorthand 89 | for( let i = 0; i < numNodes; i++ ){ 90 | eigenvector[i] = 1; 91 | } 92 | 93 | for( let iter = 0; iter < iterations; iter++ ){ 94 | // Temp array with all 0's 95 | for( let i = 0; i < numNodes; i++ ){ 96 | temp[i] = 0; 97 | } 98 | 99 | // Multiply matrix with previous result 100 | for( let i = 0; i < numNodes; i++ ){ 101 | for( let j = 0; j < numNodes; j++ ){ 102 | let n = i * numNodes + j; 103 | 104 | temp[i] += matrix[n] * eigenvector[j]; 105 | } 106 | } 107 | 108 | inPlaceSumNormalize( temp ); 109 | previous = eigenvector; 110 | eigenvector = temp; 111 | temp = previous; 112 | 113 | let diff = 0; 114 | // Compute difference (squared module) of both vectors 115 | for( let i = 0; i < numNodes; i++ ){ 116 | let delta = previous[i] - eigenvector[i]; 117 | 118 | diff += delta * delta; 119 | } 120 | 121 | // If difference is less than the desired threshold, stop iterating 122 | if( diff < precision ){ 123 | break; 124 | } 125 | } 126 | 127 | // Construct result 128 | let res = { 129 | rank: function( node ){ 130 | node = cy.collection(node)[0]; 131 | 132 | return eigenvector[ nodes.indexOf(node) ]; 133 | } 134 | }; 135 | 136 | 137 | return res; 138 | } // pageRank 139 | 140 | }); // elesfn 141 | 142 | export default elesfn; 143 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/algorithms/tarjan-strongly-connected.js: -------------------------------------------------------------------------------- 1 | let tarjanStronglyConnected = function() { 2 | 3 | let eles = this; 4 | let nodes = {}; 5 | let index = 0; 6 | let components = []; 7 | let stack = []; 8 | let cut = eles.spawn(eles); 9 | 10 | const stronglyConnectedSearch = sourceNodeId => { 11 | stack.push(sourceNodeId); 12 | nodes[sourceNodeId] = { 13 | index : index, 14 | low : index++, 15 | explored : false 16 | }; 17 | 18 | let connectedEdges = eles.getElementById(sourceNodeId) 19 | .connectedEdges() 20 | .intersection(eles); 21 | 22 | connectedEdges.forEach(edge => { 23 | let targetNodeId = edge.target().id(); 24 | if (targetNodeId !== sourceNodeId) { 25 | if (!(targetNodeId in nodes)) { 26 | stronglyConnectedSearch(targetNodeId); 27 | } 28 | if (!(nodes[targetNodeId].explored)) { 29 | nodes[sourceNodeId].low = Math.min(nodes[sourceNodeId].low, 30 | nodes[targetNodeId].low); 31 | } 32 | } 33 | }); 34 | 35 | if (nodes[sourceNodeId].index === nodes[sourceNodeId].low) { 36 | let componentNodes = eles.spawn(); 37 | for (;;) { 38 | const nodeId = stack.pop(); 39 | componentNodes.merge(eles.getElementById(nodeId)); 40 | nodes[nodeId].low = nodes[sourceNodeId].index; 41 | nodes[nodeId].explored = true; 42 | if (nodeId === sourceNodeId) { 43 | break; 44 | } 45 | } 46 | 47 | let componentEdges = componentNodes.edgesWith(componentNodes); 48 | let component = componentNodes.merge(componentEdges); 49 | components.push(component); 50 | cut = cut.difference(component); 51 | } 52 | }; 53 | 54 | eles.forEach(ele => { 55 | if (ele.isNode()) { 56 | let nodeId = ele.id(); 57 | if (!(nodeId in nodes)) { 58 | stronglyConnectedSearch(nodeId); 59 | } 60 | } 61 | }); 62 | 63 | return { 64 | cut, 65 | components 66 | }; 67 | 68 | }; 69 | 70 | export default { 71 | tarjanStronglyConnected, 72 | tsc: tarjanStronglyConnected, 73 | tscc: tarjanStronglyConnected, 74 | tarjanStronglyConnectedComponents: tarjanStronglyConnected 75 | }; 76 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/animation.js: -------------------------------------------------------------------------------- 1 | import define from '../define'; 2 | 3 | let elesfn = ({ 4 | animate: define.animate(), 5 | animation: define.animation(), 6 | animated: define.animated(), 7 | clearQueue: define.clearQueue(), 8 | delay: define.delay(), 9 | delayAnimation: define.delayAnimation(), 10 | stop: define.stop() 11 | }); 12 | 13 | export default elesfn; 14 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/cache-traversal-call.js: -------------------------------------------------------------------------------- 1 | import * as is from '../is'; 2 | import * as util from '../util'; 3 | 4 | let cache = function( fn, name ){ 5 | return function traversalCache( arg1, arg2, arg3, arg4 ){ 6 | let selectorOrEles = arg1; 7 | let eles = this; 8 | let key; 9 | 10 | if( selectorOrEles == null ){ 11 | key = ''; 12 | } else if( is.elementOrCollection( selectorOrEles ) && selectorOrEles.length === 1 ){ 13 | key = selectorOrEles.id(); 14 | } 15 | 16 | if( eles.length === 1 && key ){ 17 | let _p = eles[0]._private; 18 | let tch = _p.traversalCache = _p.traversalCache || {}; 19 | let ch = tch[ name ] = tch[ name ] || []; 20 | let hash = util.hashString( key ); 21 | let cacheHit = ch[ hash ]; 22 | 23 | if( cacheHit ){ 24 | return cacheHit; 25 | } else { 26 | return ( ch[ hash ] = fn.call( eles, arg1, arg2, arg3, arg4 ) ); 27 | } 28 | } else { 29 | return fn.call( eles, arg1, arg2, arg3, arg4 ); 30 | } 31 | }; 32 | }; 33 | 34 | export default cache; 35 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/class.js: -------------------------------------------------------------------------------- 1 | import Set from '../set'; 2 | import * as is from '../is'; 3 | 4 | let elesfn = ({ 5 | classes: function( classes ){ 6 | let self = this; 7 | 8 | if( classes === undefined ){ 9 | let ret = []; 10 | 11 | self[0]._private.classes.forEach(cls => ret.push(cls)); 12 | 13 | return ret; 14 | } else if( !is.array( classes ) ){ 15 | // extract classes from string 16 | classes = ( classes || '' ).match( /\S+/g ) || []; 17 | } 18 | 19 | let changed = []; 20 | let classesSet = new Set( classes ); 21 | 22 | // check and update each ele 23 | for( let j = 0; j < self.length; j++ ){ 24 | let ele = self[ j ]; 25 | let _p = ele._private; 26 | let eleClasses = _p.classes; 27 | let changedEle = false; 28 | 29 | // check if ele has all of the passed classes 30 | for( let i = 0; i < classes.length; i++ ){ 31 | let cls = classes[i]; 32 | let eleHasClass = eleClasses.has(cls); 33 | 34 | if( !eleHasClass ){ 35 | changedEle = true; 36 | break; 37 | } 38 | } 39 | 40 | // check if ele has classes outside of those passed 41 | if( !changedEle ){ 42 | changedEle = eleClasses.size !== classes.length; 43 | } 44 | 45 | if( changedEle ){ 46 | _p.classes = classesSet; 47 | 48 | changed.push( ele ); 49 | } 50 | } 51 | 52 | // trigger update style on those eles that had class changes 53 | if( changed.length > 0 ){ 54 | this.spawn( changed ) 55 | .updateStyle() 56 | .emit( 'class' ) 57 | ; 58 | } 59 | 60 | return self; 61 | }, 62 | 63 | addClass: function( classes ){ 64 | return this.toggleClass( classes, true ); 65 | }, 66 | 67 | hasClass: function( className ){ 68 | let ele = this[0]; 69 | return ( ele != null && ele._private.classes.has(className) ); 70 | }, 71 | 72 | toggleClass: function( classes, toggle ){ 73 | if( !is.array( classes ) ){ 74 | // extract classes from string 75 | classes = classes.match( /\S+/g ) || []; 76 | } 77 | let self = this; 78 | let toggleUndefd = toggle === undefined; 79 | let changed = []; // eles who had classes changed 80 | 81 | for( let i = 0, il = self.length; i < il; i++ ){ 82 | let ele = self[ i ]; 83 | let eleClasses = ele._private.classes; 84 | let changedEle = false; 85 | 86 | for( let j = 0; j < classes.length; j++ ){ 87 | let cls = classes[ j ]; 88 | let hasClass = eleClasses.has(cls); 89 | let changedNow = false; 90 | 91 | if( toggle || (toggleUndefd && !hasClass) ){ 92 | eleClasses.add(cls); 93 | changedNow = true; 94 | } else if( !toggle || (toggleUndefd && hasClass) ){ 95 | eleClasses.delete(cls); 96 | changedNow = true; 97 | } 98 | 99 | if( !changedEle && changedNow ){ 100 | changed.push( ele ); 101 | changedEle = true; 102 | } 103 | 104 | } // for j classes 105 | } // for i eles 106 | 107 | // trigger update style on those eles that had class changes 108 | if( changed.length > 0 ){ 109 | this.spawn( changed ) 110 | .updateStyle() 111 | .emit( 'class' ) 112 | ; 113 | } 114 | 115 | return self; 116 | }, 117 | 118 | removeClass: function( classes ){ 119 | return this.toggleClass( classes, false ); 120 | }, 121 | 122 | flashClass: function( classes, duration ){ 123 | let self = this; 124 | 125 | if( duration == null ){ 126 | duration = 250; 127 | } else if( duration === 0 ){ 128 | return self; // nothing to do really 129 | } 130 | 131 | self.addClass( classes ); 132 | setTimeout( function(){ 133 | self.removeClass( classes ); 134 | }, duration ); 135 | 136 | return self; 137 | } 138 | }); 139 | 140 | elesfn.className = elesfn.classNames = elesfn.classes; 141 | 142 | export default elesfn; 143 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/comparators.js: -------------------------------------------------------------------------------- 1 | import Selector from '../selector'; 2 | 3 | let elesfn = ({ 4 | allAre: function( selector ){ 5 | let selObj = new Selector( selector ); 6 | 7 | return this.every(function( ele ){ 8 | return selObj.matches( ele ); 9 | }); 10 | }, 11 | 12 | is: function( selector ){ 13 | let selObj = new Selector( selector ); 14 | 15 | return this.some(function( ele ){ 16 | return selObj.matches( ele ); 17 | }); 18 | }, 19 | 20 | some: function( fn, thisArg ){ 21 | for( let i = 0; i < this.length; i++ ){ 22 | let ret = !thisArg ? fn( this[ i ], i, this ) : fn.apply( thisArg, [ this[ i ], i, this ] ); 23 | 24 | if( ret ){ 25 | return true; 26 | } 27 | } 28 | 29 | return false; 30 | }, 31 | 32 | every: function( fn, thisArg ){ 33 | for( let i = 0; i < this.length; i++ ){ 34 | let ret = !thisArg ? fn( this[ i ], i, this ) : fn.apply( thisArg, [ this[ i ], i, this ] ); 35 | 36 | if( !ret ){ 37 | return false; 38 | } 39 | } 40 | 41 | return true; 42 | }, 43 | 44 | same: function( collection ){ 45 | // cheap collection ref check 46 | if( this === collection ){ return true; } 47 | 48 | collection = this.cy().collection( collection ); 49 | 50 | let thisLength = this.length; 51 | let collectionLength = collection.length; 52 | 53 | // cheap length check 54 | if( thisLength !== collectionLength ){ return false; } 55 | 56 | // cheap element ref check 57 | if( thisLength === 1 ){ return this[0] === collection[0]; } 58 | 59 | return this.every(function( ele ){ 60 | return collection.hasElementWithId( ele.id() ); 61 | }); 62 | }, 63 | 64 | anySame: function( collection ){ 65 | collection = this.cy().collection( collection ); 66 | 67 | return this.some(function( ele ){ 68 | return collection.hasElementWithId( ele.id() ); 69 | }); 70 | }, 71 | 72 | allAreNeighbors: function( collection ){ 73 | collection = this.cy().collection( collection ); 74 | 75 | let nhood = this.neighborhood(); 76 | 77 | return collection.every(function( ele ){ 78 | return nhood.hasElementWithId( ele.id() ); 79 | }); 80 | }, 81 | 82 | contains: function( collection ){ 83 | collection = this.cy().collection( collection ); 84 | 85 | let self = this; 86 | 87 | return collection.every(function( ele ){ 88 | return self.hasElementWithId( ele.id() ); 89 | }); 90 | } 91 | }); 92 | 93 | elesfn.allAreNeighbours = elesfn.allAreNeighbors; 94 | elesfn.has = elesfn.contains; 95 | elesfn.equal = elesfn.equals = elesfn.same; 96 | 97 | export default elesfn; 98 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/data.js: -------------------------------------------------------------------------------- 1 | import define from '../define'; 2 | 3 | let fn, elesfn; 4 | 5 | fn = elesfn = ({ 6 | 7 | data: define.data( { 8 | field: 'data', 9 | bindingEvent: 'data', 10 | allowBinding: true, 11 | allowSetting: true, 12 | settingEvent: 'data', 13 | settingTriggersEvent: true, 14 | triggerFnName: 'trigger', 15 | allowGetting: true, 16 | immutableKeys: { 17 | 'id': true, 18 | 'source': true, 19 | 'target': true, 20 | 'parent': true 21 | }, 22 | updateStyle: true 23 | } ), 24 | 25 | removeData: define.removeData( { 26 | field: 'data', 27 | event: 'data', 28 | triggerFnName: 'trigger', 29 | triggerEvent: true, 30 | immutableKeys: { 31 | 'id': true, 32 | 'source': true, 33 | 'target': true, 34 | 'parent': true 35 | }, 36 | updateStyle: true 37 | } ), 38 | 39 | scratch: define.data( { 40 | field: 'scratch', 41 | bindingEvent: 'scratch', 42 | allowBinding: true, 43 | allowSetting: true, 44 | settingEvent: 'scratch', 45 | settingTriggersEvent: true, 46 | triggerFnName: 'trigger', 47 | allowGetting: true, 48 | updateStyle: true 49 | } ), 50 | 51 | removeScratch: define.removeData( { 52 | field: 'scratch', 53 | event: 'scratch', 54 | triggerFnName: 'trigger', 55 | triggerEvent: true, 56 | updateStyle: true 57 | } ), 58 | 59 | rscratch: define.data( { 60 | field: 'rscratch', 61 | allowBinding: false, 62 | allowSetting: true, 63 | settingTriggersEvent: false, 64 | allowGetting: true 65 | } ), 66 | 67 | removeRscratch: define.removeData( { 68 | field: 'rscratch', 69 | triggerEvent: false 70 | } ), 71 | 72 | id: function(){ 73 | let ele = this[0]; 74 | 75 | if( ele ){ 76 | return ele._private.data.id; 77 | } 78 | } 79 | 80 | }); 81 | 82 | // aliases 83 | fn.attr = fn.data; 84 | fn.removeAttr = fn.removeData; 85 | 86 | export default elesfn; 87 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/degree.js: -------------------------------------------------------------------------------- 1 | import * as util from '../util'; 2 | 3 | let elesfn = {}; 4 | 5 | function defineDegreeFunction( callback ){ 6 | return function( includeLoops ){ 7 | let self = this; 8 | 9 | if( includeLoops === undefined ){ 10 | includeLoops = true; 11 | } 12 | 13 | if( self.length === 0 ){ return; } 14 | 15 | if( self.isNode() && !self.removed() ){ 16 | let degree = 0; 17 | let node = self[0]; 18 | let connectedEdges = node._private.edges; 19 | 20 | for( let i = 0; i < connectedEdges.length; i++ ){ 21 | let edge = connectedEdges[ i ]; 22 | 23 | if( !includeLoops && edge.isLoop() ){ 24 | continue; 25 | } 26 | 27 | degree += callback( node, edge ); 28 | } 29 | 30 | return degree; 31 | } else { 32 | return; 33 | } 34 | }; 35 | } 36 | 37 | util.extend( elesfn, { 38 | degree: defineDegreeFunction( function( node, edge ){ 39 | if( edge.source().same( edge.target() ) ){ 40 | return 2; 41 | } else { 42 | return 1; 43 | } 44 | } ), 45 | 46 | indegree: defineDegreeFunction( function( node, edge ){ 47 | if( edge.target().same( node ) ){ 48 | return 1; 49 | } else { 50 | return 0; 51 | } 52 | } ), 53 | 54 | outdegree: defineDegreeFunction( function( node, edge ){ 55 | if( edge.source().same( node ) ){ 56 | return 1; 57 | } else { 58 | return 0; 59 | } 60 | } ) 61 | } ); 62 | 63 | function defineDegreeBoundsFunction( degreeFn, callback ){ 64 | return function( includeLoops ){ 65 | let ret; 66 | let nodes = this.nodes(); 67 | 68 | for( let i = 0; i < nodes.length; i++ ){ 69 | let ele = nodes[ i ]; 70 | let degree = ele[ degreeFn ]( includeLoops ); 71 | if( degree !== undefined && (ret === undefined || callback( degree, ret )) ){ 72 | ret = degree; 73 | } 74 | } 75 | 76 | return ret; 77 | }; 78 | } 79 | 80 | util.extend( elesfn, { 81 | minDegree: defineDegreeBoundsFunction( 'degree', function( degree, min ){ 82 | return degree < min; 83 | } ), 84 | 85 | maxDegree: defineDegreeBoundsFunction( 'degree', function( degree, max ){ 86 | return degree > max; 87 | } ), 88 | 89 | minIndegree: defineDegreeBoundsFunction( 'indegree', function( degree, min ){ 90 | return degree < min; 91 | } ), 92 | 93 | maxIndegree: defineDegreeBoundsFunction( 'indegree', function( degree, max ){ 94 | return degree > max; 95 | } ), 96 | 97 | minOutdegree: defineDegreeBoundsFunction( 'outdegree', function( degree, min ){ 98 | return degree < min; 99 | } ), 100 | 101 | maxOutdegree: defineDegreeBoundsFunction( 'outdegree', function( degree, max ){ 102 | return degree > max; 103 | } ) 104 | } ); 105 | 106 | util.extend( elesfn, { 107 | totalDegree: function( includeLoops ){ 108 | let total = 0; 109 | let nodes = this.nodes(); 110 | 111 | for( let i = 0; i < nodes.length; i++ ){ 112 | total += nodes[ i ].degree( includeLoops ); 113 | } 114 | 115 | return total; 116 | } 117 | } ); 118 | 119 | export default elesfn; 120 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/dimensions/edge-points.js: -------------------------------------------------------------------------------- 1 | import * as math from '../../math'; 2 | 3 | const ifEdge = (ele, getValue) => { 4 | if( ele.isEdge() ){ 5 | return getValue( ele ); 6 | } 7 | }; 8 | 9 | const ifEdgeRenderedPosition = (ele, getPoint) => { 10 | if( ele.isEdge() ){ 11 | let cy = ele.cy(); 12 | 13 | return math.modelToRenderedPosition( getPoint( ele ), cy.zoom(), cy.pan() ); 14 | } 15 | }; 16 | 17 | const ifEdgeRenderedPositions = (ele, getPoints) => { 18 | if( ele.isEdge() ){ 19 | let cy = ele.cy(); 20 | let pan = cy.pan(); 21 | let zoom = cy.zoom(); 22 | 23 | return getPoints( ele ).map( p => math.modelToRenderedPosition( p, zoom, pan ) ); 24 | } 25 | }; 26 | 27 | const controlPoints = ele => ele.renderer().getControlPoints( ele ); 28 | const segmentPoints = ele => ele.renderer().getSegmentPoints( ele ); 29 | const sourceEndpoint = ele => ele.renderer().getSourceEndpoint( ele ); 30 | const targetEndpoint = ele => ele.renderer().getTargetEndpoint( ele ); 31 | const midpoint = ele => ele.renderer().getEdgeMidpoint( ele ); 32 | 33 | const pts = { 34 | controlPoints: { get: controlPoints, mult: true }, 35 | segmentPoints: { get: segmentPoints, mult: true }, 36 | sourceEndpoint: { get: sourceEndpoint }, 37 | targetEndpoint: { get: targetEndpoint }, 38 | midpoint: { get: midpoint } 39 | }; 40 | 41 | const renderedName = name => 'rendered' + name[0].toUpperCase() + name.substr(1); 42 | 43 | export default Object.keys( pts ).reduce( ( obj, name ) => { 44 | let spec = pts[ name ]; 45 | let rName = renderedName( name ); 46 | 47 | obj[ name ] = function(){ return ifEdge( this, spec.get ); }; 48 | 49 | if( spec.mult ){ 50 | obj[ rName ] = function(){ return ifEdgeRenderedPositions( this, spec.get ); }; 51 | } else { 52 | obj[ rName ] = function(){ return ifEdgeRenderedPosition( this, spec.get ); }; 53 | } 54 | 55 | return obj; 56 | }, {} ); 57 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/dimensions/index.js: -------------------------------------------------------------------------------- 1 | import * as util from '../../util'; 2 | import position from './position'; 3 | import bounds from './bounds'; 4 | import widthHeight from './width-height'; 5 | import edgePoints from './edge-points'; 6 | 7 | export default util.assign( {}, position, bounds, widthHeight, edgePoints ); 8 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/dimensions/width-height.js: -------------------------------------------------------------------------------- 1 | import * as util from '../../util'; 2 | 3 | let fn, elesfn; 4 | 5 | fn = elesfn = {}; 6 | 7 | let defineDimFns = function( opts ){ 8 | opts.uppercaseName = util.capitalize( opts.name ); 9 | opts.autoName = 'auto' + opts.uppercaseName; 10 | opts.labelName = 'label' + opts.uppercaseName; 11 | opts.outerName = 'outer' + opts.uppercaseName; 12 | opts.uppercaseOuterName = util.capitalize( opts.outerName ); 13 | 14 | fn[ opts.name ] = function dimImpl(){ 15 | let ele = this[0]; 16 | let _p = ele._private; 17 | let cy = _p.cy; 18 | let styleEnabled = cy._private.styleEnabled; 19 | 20 | if( ele ){ 21 | if( styleEnabled ){ 22 | if( ele.isParent() ){ 23 | ele.updateCompoundBounds(); 24 | 25 | return _p[ opts.autoName ] || 0; 26 | } 27 | 28 | let d = ele.pstyle( opts.name ); 29 | 30 | switch( d.strValue ){ 31 | case 'label': 32 | ele.recalculateRenderedStyle(); 33 | 34 | return _p.rstyle[ opts.labelName ] || 0; 35 | 36 | default: 37 | return d.pfValue; 38 | } 39 | } else { 40 | return 1; 41 | } 42 | } 43 | }; 44 | 45 | fn[ 'outer' + opts.uppercaseName ] = function outerDimImpl(){ 46 | let ele = this[0]; 47 | let _p = ele._private; 48 | let cy = _p.cy; 49 | let styleEnabled = cy._private.styleEnabled; 50 | 51 | if( ele ){ 52 | if( styleEnabled ){ 53 | let dim = ele[ opts.name ](); 54 | let border = ele.pstyle( 'border-width' ).pfValue; // n.b. 1/2 each side 55 | let padding = 2 * ele.padding(); 56 | 57 | return dim + border + padding; 58 | } else { 59 | return 1; 60 | } 61 | } 62 | }; 63 | 64 | fn[ 'rendered' + opts.uppercaseName ] = function renderedDimImpl(){ 65 | let ele = this[0]; 66 | 67 | if( ele ){ 68 | let d = ele[ opts.name ](); 69 | return d * this.cy().zoom(); 70 | } 71 | }; 72 | 73 | fn[ 'rendered' + opts.uppercaseOuterName ] = function renderedOuterDimImpl(){ 74 | let ele = this[0]; 75 | 76 | if( ele ){ 77 | let od = ele[ opts.outerName ](); 78 | return od * this.cy().zoom(); 79 | } 80 | }; 81 | }; 82 | 83 | defineDimFns( { 84 | name: 'width' 85 | } ); 86 | 87 | defineDimFns( { 88 | name: 'height' 89 | } ); 90 | 91 | elesfn.padding = function(){ 92 | let ele = this[0]; 93 | let _p = ele._private; 94 | if( ele.isParent() ){ 95 | ele.updateCompoundBounds(); 96 | 97 | if( _p.autoPadding !== undefined ){ 98 | return _p.autoPadding; 99 | } else { 100 | return ele.pstyle('padding').pfValue; 101 | } 102 | } else { 103 | return ele.pstyle('padding').pfValue; 104 | } 105 | }; 106 | 107 | elesfn.paddedHeight = function(){ 108 | let ele = this[0]; 109 | 110 | return ele.height() + (2 * ele.padding()); 111 | }; 112 | 113 | elesfn.paddedWidth = function(){ 114 | let ele = this[0]; 115 | 116 | return ele.width() + (2 * ele.padding()); 117 | }; 118 | 119 | export default elesfn; 120 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/events.js: -------------------------------------------------------------------------------- 1 | import Emitter from '../emitter'; 2 | import define from '../define'; 3 | import * as is from '../is'; 4 | import Selector from '../selector'; 5 | 6 | let emitterOptions = { 7 | qualifierCompare: function( selector1, selector2 ){ 8 | if( selector1 == null || selector2 == null ){ 9 | return selector1 == null && selector2 == null; 10 | } else { 11 | return selector1.sameText( selector2 ); 12 | } 13 | }, 14 | eventMatches: function( ele, listener, eventObj ){ 15 | let selector = listener.qualifier; 16 | 17 | if( selector != null ){ 18 | return ele !== eventObj.target && is.element( eventObj.target ) && selector.matches( eventObj.target ); 19 | } 20 | 21 | return true; 22 | }, 23 | addEventFields: function( ele, evt ){ 24 | evt.cy = ele.cy(); 25 | evt.target = ele; 26 | }, 27 | callbackContext: function( ele, listener, eventObj ){ 28 | return listener.qualifier != null ? eventObj.target : ele; 29 | }, 30 | beforeEmit: function( context, listener/*, eventObj*/ ){ 31 | if( listener.conf && listener.conf.once ){ 32 | listener.conf.onceCollection.removeListener( listener.event, listener.qualifier, listener.callback ); 33 | } 34 | }, 35 | bubble: function(){ 36 | return true; 37 | }, 38 | parent: function( ele ){ 39 | return ele.isChild() ? ele.parent() : ele.cy(); 40 | } 41 | }; 42 | 43 | let argSelector = function( arg ){ 44 | if( is.string(arg) ){ 45 | return new Selector( arg ); 46 | } else { 47 | return arg; 48 | } 49 | }; 50 | 51 | let elesfn = ({ 52 | createEmitter: function(){ 53 | for( let i = 0; i < this.length; i++ ){ 54 | let ele = this[i]; 55 | let _p = ele._private; 56 | 57 | if( !_p.emitter ){ 58 | _p.emitter = new Emitter( emitterOptions, ele ); 59 | } 60 | } 61 | 62 | return this; 63 | }, 64 | 65 | emitter: function(){ 66 | return this._private.emitter; 67 | }, 68 | 69 | on: function( events, selector, callback ){ 70 | let argSel = argSelector(selector); 71 | 72 | for( let i = 0; i < this.length; i++ ){ 73 | let ele = this[i]; 74 | 75 | ele.emitter().on( events, argSel, callback ); 76 | } 77 | 78 | return this; 79 | }, 80 | 81 | removeListener: function( events, selector, callback ){ 82 | let argSel = argSelector(selector); 83 | 84 | for( let i = 0; i < this.length; i++ ){ 85 | let ele = this[i]; 86 | 87 | ele.emitter().removeListener( events, argSel, callback ); 88 | } 89 | 90 | return this; 91 | }, 92 | 93 | removeAllListeners: function(){ 94 | for( let i = 0; i < this.length; i++ ){ 95 | let ele = this[i]; 96 | 97 | ele.emitter().removeAllListeners(); 98 | } 99 | 100 | return this; 101 | }, 102 | 103 | one: function( events, selector, callback ){ 104 | let argSel = argSelector(selector); 105 | 106 | for( let i = 0; i < this.length; i++ ){ 107 | let ele = this[i]; 108 | 109 | ele.emitter().one( events, argSel, callback ); 110 | } 111 | 112 | return this; 113 | }, 114 | 115 | once: function( events, selector, callback ){ 116 | let argSel = argSelector(selector); 117 | 118 | for( let i = 0; i < this.length; i++ ){ 119 | let ele = this[i]; 120 | 121 | ele.emitter().on( events, argSel, callback, { 122 | once: true, 123 | onceCollection: this 124 | } ); 125 | } 126 | }, 127 | 128 | emit: function( events, extraParams ){ 129 | for( let i = 0; i < this.length; i++ ){ 130 | let ele = this[i]; 131 | 132 | ele.emitter().emit( events, extraParams ); 133 | } 134 | 135 | return this; 136 | }, 137 | 138 | emitAndNotify: function( event, extraParams ){ // for internal use only 139 | if( this.length === 0 ){ return; } // empty collections don't need to notify anything 140 | 141 | // notify renderer 142 | this.cy().notify( event, this ); 143 | 144 | this.emit( event, extraParams ); 145 | 146 | return this; 147 | } 148 | }); 149 | 150 | define.eventAliasesOn( elesfn ); 151 | 152 | export default elesfn; 153 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/group.js: -------------------------------------------------------------------------------- 1 | let elesfn = ({ 2 | isNode: function(){ 3 | return this.group() === 'nodes'; 4 | }, 5 | 6 | isEdge: function(){ 7 | return this.group() === 'edges'; 8 | }, 9 | 10 | isLoop: function(){ 11 | return this.isEdge() && this.source()[0] === this.target()[0]; 12 | }, 13 | 14 | isSimple: function(){ 15 | return this.isEdge() && this.source()[0] !== this.target()[0]; 16 | }, 17 | 18 | group: function(){ 19 | let ele = this[0]; 20 | 21 | if( ele ){ 22 | return ele._private.group; 23 | } 24 | } 25 | }); 26 | 27 | 28 | export default elesfn; 29 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/iteration.js: -------------------------------------------------------------------------------- 1 | import * as is from '../is' ; 2 | import zIndexSort from './zsort' ; 3 | import * as util from '../util'; 4 | 5 | let elesfn = ({ 6 | forEach: function( fn, thisArg ){ 7 | if( is.fn( fn ) ){ 8 | let N = this.length; 9 | 10 | for( let i = 0; i < N; i++ ){ 11 | let ele = this[ i ]; 12 | let ret = thisArg ? fn.apply( thisArg, [ ele, i, this ] ) : fn( ele, i, this ); 13 | 14 | if( ret === false ){ break; } // exit each early on return false 15 | } 16 | } 17 | 18 | return this; 19 | }, 20 | 21 | toArray: function(){ 22 | let array = []; 23 | 24 | for( let i = 0; i < this.length; i++ ){ 25 | array.push( this[ i ] ); 26 | } 27 | 28 | return array; 29 | }, 30 | 31 | slice: function( start, end ){ 32 | let array = []; 33 | let thisSize = this.length; 34 | 35 | if( end == null ){ 36 | end = thisSize; 37 | } 38 | 39 | if( start == null ){ 40 | start = 0; 41 | } 42 | 43 | if( start < 0 ){ 44 | start = thisSize + start; 45 | } 46 | 47 | if( end < 0 ){ 48 | end = thisSize + end; 49 | } 50 | 51 | for( let i = start; i >= 0 && i < end && i < thisSize; i++ ){ 52 | array.push( this[ i ] ); 53 | } 54 | 55 | return this.spawn( array ); 56 | }, 57 | 58 | size: function(){ 59 | return this.length; 60 | }, 61 | 62 | eq: function( i ){ 63 | return this[ i ] || this.spawn(); 64 | }, 65 | 66 | first: function(){ 67 | return this[0] || this.spawn(); 68 | }, 69 | 70 | last: function(){ 71 | return this[ this.length - 1 ] || this.spawn(); 72 | }, 73 | 74 | empty: function(){ 75 | return this.length === 0; 76 | }, 77 | 78 | nonempty: function(){ 79 | return !this.empty(); 80 | }, 81 | 82 | sort: function( sortFn ){ 83 | if( !is.fn( sortFn ) ){ 84 | return this; 85 | } 86 | 87 | let sorted = this.toArray().sort( sortFn ); 88 | 89 | return this.spawn( sorted ); 90 | }, 91 | 92 | sortByZIndex: function(){ 93 | return this.sort( zIndexSort ); 94 | }, 95 | 96 | zDepth: function(){ 97 | let ele = this[0]; 98 | if( !ele ){ return undefined; } 99 | 100 | // let cy = ele.cy(); 101 | let _p = ele._private; 102 | let group = _p.group; 103 | 104 | if( group === 'nodes' ){ 105 | let depth = _p.data.parent ? ele.parents().size() : 0; 106 | 107 | if( !ele.isParent() ){ 108 | return util.MAX_INT - 1; // childless nodes always on top 109 | } 110 | 111 | return depth; 112 | } else { 113 | let src = _p.source; 114 | let tgt = _p.target; 115 | let srcDepth = src.zDepth(); 116 | let tgtDepth = tgt.zDepth(); 117 | 118 | return Math.max( srcDepth, tgtDepth, 0 ); // depth of deepest parent 119 | } 120 | } 121 | }); 122 | 123 | elesfn.each = elesfn.forEach; 124 | 125 | const defineSymbolIterator = () => { 126 | const typeofUndef = typeof undefined; 127 | const isIteratorSupported = typeof Symbol != typeofUndef && typeof Symbol.iterator != typeofUndef; // eslint-disable-line no-undef 128 | 129 | if (isIteratorSupported) { 130 | elesfn[Symbol.iterator] = function() { // eslint-disable-line no-undef 131 | let entry = { value: undefined, done: false }; 132 | let i = 0; 133 | let length = this.length; 134 | 135 | return { 136 | next: () => { 137 | if ( i < length ) { 138 | entry.value = this[i++]; 139 | } else { 140 | entry.value = undefined; 141 | entry.done = true; 142 | } 143 | 144 | return entry; 145 | }, 146 | [Symbol.iterator]: function() { // eslint-disable-line no-undef 147 | return this; 148 | } 149 | }; 150 | }; 151 | } 152 | }; 153 | defineSymbolIterator(); 154 | 155 | export default elesfn; 156 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/switch-functions.js: -------------------------------------------------------------------------------- 1 | import * as is from '../is'; 2 | 3 | const elesfn = {}; 4 | 5 | function defineSwitchFunction( params ){ 6 | return function(){ 7 | let args = arguments; 8 | let changedEles = []; 9 | 10 | // e.g. cy.nodes().select( data, handler ) 11 | if( args.length === 2 ){ 12 | let data = args[0]; 13 | let handler = args[1]; 14 | this.on( params.event, data, handler ); 15 | } 16 | 17 | // e.g. cy.nodes().select( handler ) 18 | else if( args.length === 1 && is.fn(args[0]) ){ 19 | let handler = args[0]; 20 | this.on( params.event, handler ); 21 | } 22 | 23 | // e.g. cy.nodes().select() 24 | // e.g. (private) cy.nodes().select(['tapselect']) 25 | else if( args.length === 0 || (args.length === 1 && is.array(args[0])) ){ 26 | let addlEvents = args.length === 1 ? args[0] : null; 27 | 28 | for( let i = 0; i < this.length; i++ ){ 29 | let ele = this[ i ]; 30 | let able = !params.ableField || ele._private[ params.ableField ]; 31 | let changed = ele._private[ params.field ] != params.value; 32 | 33 | if( params.overrideAble ){ 34 | let overrideAble = params.overrideAble( ele ); 35 | 36 | if( overrideAble !== undefined ){ 37 | able = overrideAble; 38 | 39 | if( !overrideAble ){ return this; } // to save cycles assume not able for all on override 40 | } 41 | } 42 | 43 | if( able ){ 44 | ele._private[ params.field ] = params.value; 45 | 46 | if( changed ){ 47 | changedEles.push( ele ); 48 | } 49 | } 50 | } 51 | 52 | let changedColl = this.spawn( changedEles ); 53 | changedColl.updateStyle(); // change of state => possible change of style 54 | changedColl.emit( params.event ); 55 | 56 | if( addlEvents ){ 57 | changedColl.emit( addlEvents ); 58 | } 59 | } 60 | 61 | return this; 62 | }; 63 | } 64 | 65 | function defineSwitchSet( params ){ 66 | elesfn[ params.field ] = function(){ 67 | let ele = this[0]; 68 | 69 | if( ele ){ 70 | if( params.overrideField ){ 71 | let val = params.overrideField( ele ); 72 | 73 | if( val !== undefined ){ 74 | return val; 75 | } 76 | } 77 | 78 | return ele._private[ params.field ]; 79 | } 80 | }; 81 | 82 | elesfn[ params.on ] = defineSwitchFunction( { 83 | event: params.on, 84 | field: params.field, 85 | ableField: params.ableField, 86 | overrideAble: params.overrideAble, 87 | value: true 88 | } ); 89 | 90 | elesfn[ params.off ] = defineSwitchFunction( { 91 | event: params.off, 92 | field: params.field, 93 | ableField: params.ableField, 94 | overrideAble: params.overrideAble, 95 | value: false 96 | } ); 97 | } 98 | 99 | defineSwitchSet( { 100 | field: 'locked', 101 | overrideField: function( ele ){ 102 | return ele.cy().autolock() ? true : undefined; 103 | }, 104 | on: 'lock', 105 | off: 'unlock' 106 | } ); 107 | 108 | defineSwitchSet( { 109 | field: 'grabbable', 110 | overrideField: function( ele ){ 111 | return ele.cy().autoungrabify() || ele.pannable() ? false : undefined; 112 | }, 113 | on: 'grabify', 114 | off: 'ungrabify' 115 | } ); 116 | 117 | defineSwitchSet( { 118 | field: 'selected', 119 | ableField: 'selectable', 120 | overrideAble: function( ele ){ 121 | return ele.cy().autounselectify() ? false : undefined; 122 | }, 123 | on: 'select', 124 | off: 'unselect' 125 | } ); 126 | 127 | defineSwitchSet( { 128 | field: 'selectable', 129 | overrideField: function( ele ){ 130 | return ele.cy().autounselectify() ? false : undefined; 131 | }, 132 | on: 'selectify', 133 | off: 'unselectify' 134 | } ); 135 | 136 | elesfn.deselect = elesfn.unselect; 137 | 138 | elesfn.grabbed = function(){ 139 | let ele = this[0]; 140 | if( ele ){ 141 | return ele._private.grabbed; 142 | } 143 | }; 144 | 145 | defineSwitchSet( { 146 | field: 'active', 147 | on: 'activate', 148 | off: 'unactivate' 149 | } ); 150 | 151 | defineSwitchSet( { 152 | field: 'pannable', 153 | on: 'panify', 154 | off: 'unpanify' 155 | } ); 156 | 157 | elesfn.inactive = function(){ 158 | let ele = this[0]; 159 | if( ele ){ 160 | return !ele._private.active; 161 | } 162 | }; 163 | 164 | export default elesfn; 165 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/collection/zsort.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Elements are drawn in a specific order based on compound depth (low to high), the element type (nodes above edges), 3 | * and z-index (low to high). These styles affect how this applies: 4 | * 5 | * z-compound-depth: May be `bottom | orphan | auto | top`. The first drawn is `bottom`, then `orphan` which is the 6 | * same depth as the root of the compound graph, followed by the default value `auto` which draws in order from 7 | * root to leaves of the compound graph. The last drawn is `top`. 8 | * z-index-compare: May be `auto | manual`. The default value is `auto` which always draws edges under nodes. 9 | * `manual` ignores this convention and draws based on the `z-index` value setting. 10 | * z-index: An integer value that affects the relative draw order of elements. In general, an element with a higher 11 | * `z-index` will be drawn on top of an element with a lower `z-index`. 12 | */ 13 | import * as util from '../util'; 14 | 15 | let zIndexSort = function( a, b ){ 16 | let cy = a.cy(); 17 | let hasCompoundNodes = cy.hasCompoundNodes(); 18 | 19 | function getDepth(ele){ 20 | let style = ele.pstyle( 'z-compound-depth' ); 21 | if ( style.value === 'auto' ){ 22 | return hasCompoundNodes ? ele.zDepth() : 0; 23 | } else if ( style.value === 'bottom' ){ 24 | return -1; 25 | } else if ( style.value === 'top' ){ 26 | return util.MAX_INT; 27 | } 28 | // 'orphan' 29 | return 0; 30 | } 31 | let depthDiff = getDepth(a) - getDepth(b); 32 | if ( depthDiff !== 0 ){ 33 | return depthDiff; 34 | } 35 | 36 | function getEleDepth(ele){ 37 | let style = ele.pstyle( 'z-index-compare' ); 38 | if ( style.value === 'auto' ){ 39 | return ele.isNode() ? 1 : 0; 40 | } 41 | // 'manual' 42 | return 0; 43 | } 44 | let eleDiff = getEleDepth(a) - getEleDepth(b); 45 | if ( eleDiff !== 0 ){ 46 | return eleDiff; 47 | } 48 | 49 | let zDiff = a.pstyle( 'z-index' ).value - b.pstyle( 'z-index' ).value; 50 | if ( zDiff !== 0 ){ 51 | return zDiff; 52 | } 53 | // compare indices in the core (order added to graph w/ last on top) 54 | return a.poolIndex() - b.poolIndex(); 55 | }; 56 | 57 | export default zIndexSort; 58 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/core/add-remove.js: -------------------------------------------------------------------------------- 1 | import * as is from '../is'; 2 | import * as util from '../util'; 3 | import Collection from '../collection'; 4 | import Element from '../collection/element'; 5 | 6 | let corefn = { 7 | add: function( opts ){ 8 | 9 | let elements; 10 | let cy = this; 11 | 12 | // add the elements 13 | if( is.elementOrCollection( opts ) ){ 14 | let eles = opts; 15 | 16 | if( eles._private.cy === cy ){ // same instance => just restore 17 | elements = eles.restore(); 18 | 19 | } else { // otherwise, copy from json 20 | let jsons = []; 21 | 22 | for( let i = 0; i < eles.length; i++ ){ 23 | let ele = eles[ i ]; 24 | jsons.push( ele.json() ); 25 | } 26 | 27 | elements = new Collection( cy, jsons ); 28 | } 29 | } 30 | 31 | // specify an array of options 32 | else if( is.array( opts ) ){ 33 | let jsons = opts; 34 | 35 | elements = new Collection( cy, jsons ); 36 | } 37 | 38 | // specify via opts.nodes and opts.edges 39 | else if( is.plainObject( opts ) && (is.array( opts.nodes ) || is.array( opts.edges )) ){ 40 | let elesByGroup = opts; 41 | let jsons = []; 42 | 43 | let grs = [ 'nodes', 'edges' ]; 44 | for( let i = 0, il = grs.length; i < il; i++ ){ 45 | let group = grs[ i ]; 46 | let elesArray = elesByGroup[ group ]; 47 | 48 | if( is.array( elesArray ) ){ 49 | 50 | for( let j = 0, jl = elesArray.length; j < jl; j++ ){ 51 | let json = util.extend( { group: group }, elesArray[ j ] ); 52 | 53 | jsons.push( json ); 54 | } 55 | } 56 | } 57 | 58 | elements = new Collection( cy, jsons ); 59 | } 60 | 61 | // specify options for one element 62 | else { 63 | let json = opts; 64 | elements = (new Element( cy, json )).collection(); 65 | } 66 | 67 | return elements; 68 | }, 69 | 70 | remove: function( collection ){ 71 | if( is.elementOrCollection( collection ) ){ 72 | // already have right ref 73 | } else if( is.string( collection ) ){ 74 | let selector = collection; 75 | collection = this.$( selector ); 76 | } 77 | 78 | return collection.remove(); 79 | } 80 | }; 81 | 82 | export default corefn; 83 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/core/animation/ease.js: -------------------------------------------------------------------------------- 1 | import * as is from '../../is'; 2 | 3 | function getEasedValue( type, start, end, percent, easingFn ){ 4 | if( percent === 1 ){ 5 | return end; 6 | } 7 | 8 | if( start === end ){ 9 | return end; 10 | } 11 | 12 | let val = easingFn( start, end, percent ); 13 | 14 | if( type == null ){ 15 | return val; 16 | } 17 | 18 | if( type.roundValue || type.color ){ 19 | val = Math.round( val ); 20 | } 21 | 22 | if( type.min !== undefined ){ 23 | val = Math.max( val, type.min ); 24 | } 25 | 26 | if( type.max !== undefined ){ 27 | val = Math.min( val, type.max ); 28 | } 29 | 30 | return val; 31 | } 32 | 33 | function getValue( prop, spec ){ 34 | if( prop.pfValue != null || prop.value != null ){ 35 | if( prop.pfValue != null && (spec == null || spec.type.units !== '%') ){ 36 | return prop.pfValue; 37 | } else { 38 | return prop.value; 39 | } 40 | } else { 41 | return prop; 42 | } 43 | } 44 | 45 | function ease( startProp, endProp, percent, easingFn, propSpec ){ 46 | let type = propSpec != null ? propSpec.type : null; 47 | 48 | if( percent < 0 ){ 49 | percent = 0; 50 | } else if( percent > 1 ){ 51 | percent = 1; 52 | } 53 | 54 | let start = getValue( startProp, propSpec ); 55 | let end = getValue( endProp, propSpec ); 56 | 57 | if( is.number( start ) && is.number( end ) ){ 58 | return getEasedValue( type, start, end, percent, easingFn ); 59 | 60 | } else if( is.array( start ) && is.array( end ) ){ 61 | let easedArr = []; 62 | 63 | for( let i = 0; i < end.length; i++ ){ 64 | let si = start[ i ]; 65 | let ei = end[ i ]; 66 | 67 | if( si != null && ei != null ){ 68 | let val = getEasedValue( type, si, ei, percent, easingFn ); 69 | 70 | easedArr.push( val ); 71 | } else { 72 | easedArr.push( ei ); 73 | } 74 | } 75 | 76 | return easedArr; 77 | } 78 | 79 | return undefined; 80 | } 81 | 82 | export default ease; 83 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/core/animation/easings.js: -------------------------------------------------------------------------------- 1 | import generateCubicBezier from './cubic-bezier'; 2 | import generateSpringRK4 from './spring'; 3 | 4 | let cubicBezier = function( t1, p1, t2, p2 ){ 5 | let bezier = generateCubicBezier( t1, p1, t2, p2 ); 6 | 7 | return function( start, end, percent ){ 8 | return start + ( end - start ) * bezier( percent ); 9 | }; 10 | }; 11 | 12 | let easings = { 13 | 'linear': function( start, end, percent ){ 14 | return start + (end - start) * percent; 15 | }, 16 | 17 | // default easings 18 | 'ease': cubicBezier( 0.25, 0.1, 0.25, 1 ), 19 | 'ease-in': cubicBezier( 0.42, 0, 1, 1 ), 20 | 'ease-out': cubicBezier( 0, 0, 0.58, 1 ), 21 | 'ease-in-out': cubicBezier( 0.42, 0, 0.58, 1 ), 22 | 23 | // sine 24 | 'ease-in-sine': cubicBezier( 0.47, 0, 0.745, 0.715 ), 25 | 'ease-out-sine': cubicBezier( 0.39, 0.575, 0.565, 1 ), 26 | 'ease-in-out-sine': cubicBezier( 0.445, 0.05, 0.55, 0.95 ), 27 | 28 | // quad 29 | 'ease-in-quad': cubicBezier( 0.55, 0.085, 0.68, 0.53 ), 30 | 'ease-out-quad': cubicBezier( 0.25, 0.46, 0.45, 0.94 ), 31 | 'ease-in-out-quad': cubicBezier( 0.455, 0.03, 0.515, 0.955 ), 32 | 33 | // cubic 34 | 'ease-in-cubic': cubicBezier( 0.55, 0.055, 0.675, 0.19 ), 35 | 'ease-out-cubic': cubicBezier( 0.215, 0.61, 0.355, 1 ), 36 | 'ease-in-out-cubic': cubicBezier( 0.645, 0.045, 0.355, 1 ), 37 | 38 | // quart 39 | 'ease-in-quart': cubicBezier( 0.895, 0.03, 0.685, 0.22 ), 40 | 'ease-out-quart': cubicBezier( 0.165, 0.84, 0.44, 1 ), 41 | 'ease-in-out-quart': cubicBezier( 0.77, 0, 0.175, 1 ), 42 | 43 | // quint 44 | 'ease-in-quint': cubicBezier( 0.755, 0.05, 0.855, 0.06 ), 45 | 'ease-out-quint': cubicBezier( 0.23, 1, 0.32, 1 ), 46 | 'ease-in-out-quint': cubicBezier( 0.86, 0, 0.07, 1 ), 47 | 48 | // expo 49 | 'ease-in-expo': cubicBezier( 0.95, 0.05, 0.795, 0.035 ), 50 | 'ease-out-expo': cubicBezier( 0.19, 1, 0.22, 1 ), 51 | 'ease-in-out-expo': cubicBezier( 1, 0, 0, 1 ), 52 | 53 | // circ 54 | 'ease-in-circ': cubicBezier( 0.6, 0.04, 0.98, 0.335 ), 55 | 'ease-out-circ': cubicBezier( 0.075, 0.82, 0.165, 1 ), 56 | 'ease-in-out-circ': cubicBezier( 0.785, 0.135, 0.15, 0.86 ), 57 | 58 | 59 | // user param easings... 60 | 61 | 'spring': function( tension, friction, duration ){ 62 | if( duration === 0 ){ // can't get a spring w/ duration 0 63 | return easings.linear; // duration 0 => jump to end so impl doesn't matter 64 | } 65 | 66 | let spring = generateSpringRK4( tension, friction, duration ); 67 | 68 | return function( start, end, percent ){ 69 | return start + (end - start) * spring( percent ); 70 | }; 71 | }, 72 | 73 | 'cubic-bezier': cubicBezier 74 | }; 75 | 76 | export default easings; 77 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/core/animation/index.js: -------------------------------------------------------------------------------- 1 | import define from '../../define'; 2 | import * as util from '../../util'; 3 | import stepAll from './step-all'; 4 | 5 | let corefn = ({ 6 | 7 | // pull in animation functions 8 | animate: define.animate(), 9 | animation: define.animation(), 10 | animated: define.animated(), 11 | clearQueue: define.clearQueue(), 12 | delay: define.delay(), 13 | delayAnimation: define.delayAnimation(), 14 | stop: define.stop(), 15 | 16 | addToAnimationPool: function( eles ){ 17 | let cy = this; 18 | 19 | if( !cy.styleEnabled() ){ return; } // save cycles when no style used 20 | 21 | cy._private.aniEles.merge( eles ); 22 | }, 23 | 24 | stopAnimationLoop: function(){ 25 | this._private.animationsRunning = false; 26 | }, 27 | 28 | startAnimationLoop: function(){ 29 | let cy = this; 30 | 31 | cy._private.animationsRunning = true; 32 | 33 | if( !cy.styleEnabled() ){ return; } // save cycles when no style used 34 | 35 | // NB the animation loop will exec in headless environments if style enabled 36 | // and explicit cy.destroy() is necessary to stop the loop 37 | 38 | function headlessStep(){ 39 | if( !cy._private.animationsRunning ){ return; } 40 | 41 | util.requestAnimationFrame( function animationStep( now ){ 42 | stepAll( now, cy ); 43 | headlessStep(); 44 | } ); 45 | } 46 | 47 | let renderer = cy.renderer(); 48 | 49 | if( renderer && renderer.beforeRender ){ // let the renderer schedule animations 50 | renderer.beforeRender( function rendererAnimationStep( willDraw, now ){ 51 | stepAll( now, cy ); 52 | }, renderer.beforeRenderPriorities.animations ); 53 | } else { // manage the animation loop ourselves 54 | headlessStep(); // first call 55 | } 56 | } 57 | 58 | }); 59 | 60 | export default corefn; 61 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/core/animation/spring.js: -------------------------------------------------------------------------------- 1 | /*! Runge-Kutta spring physics function generator. Adapted from Framer.js, copyright Koen Bok. MIT License: http://en.wikipedia.org/wiki/MIT_License */ 2 | /* Given a tension, friction, and duration, a simulation at 60FPS will first run without a defined duration in order to calculate the full path. A second pass 3 | then adjusts the time delta -- using the relation between actual time and duration -- to calculate the path for the duration-constrained animation. */ 4 | let generateSpringRK4 = (function(){ 5 | function springAccelerationForState( state ){ 6 | return (-state.tension * state.x) - (state.friction * state.v); 7 | } 8 | 9 | function springEvaluateStateWithDerivative( initialState, dt, derivative ){ 10 | let state = { 11 | x: initialState.x + derivative.dx * dt, 12 | v: initialState.v + derivative.dv * dt, 13 | tension: initialState.tension, 14 | friction: initialState.friction 15 | }; 16 | 17 | return { dx: state.v, dv: springAccelerationForState( state ) }; 18 | } 19 | 20 | function springIntegrateState( state, dt ){ 21 | let a = { 22 | dx: state.v, 23 | dv: springAccelerationForState( state ) 24 | }, 25 | b = springEvaluateStateWithDerivative( state, dt * 0.5, a ), 26 | c = springEvaluateStateWithDerivative( state, dt * 0.5, b ), 27 | d = springEvaluateStateWithDerivative( state, dt, c ), 28 | dxdt = 1.0 / 6.0 * (a.dx + 2.0 * (b.dx + c.dx) + d.dx), 29 | dvdt = 1.0 / 6.0 * (a.dv + 2.0 * (b.dv + c.dv) + d.dv); 30 | 31 | state.x = state.x + dxdt * dt; 32 | state.v = state.v + dvdt * dt; 33 | 34 | return state; 35 | } 36 | 37 | return function springRK4Factory( tension, friction, duration ){ 38 | 39 | let initState = { 40 | x: -1, 41 | v: 0, 42 | tension: null, 43 | friction: null 44 | }, 45 | path = [0], 46 | time_lapsed = 0, 47 | tolerance = 1 / 10000, 48 | DT = 16 / 1000, 49 | have_duration, dt, last_state; 50 | 51 | tension = parseFloat( tension ) || 500; 52 | friction = parseFloat( friction ) || 20; 53 | duration = duration || null; 54 | 55 | initState.tension = tension; 56 | initState.friction = friction; 57 | 58 | have_duration = duration !== null; 59 | 60 | /* Calculate the actual time it takes for this animation to complete with the provided conditions. */ 61 | if( have_duration ){ 62 | /* Run the simulation without a duration. */ 63 | time_lapsed = springRK4Factory( tension, friction ); 64 | /* Compute the adjusted time delta. */ 65 | dt = time_lapsed / duration * DT; 66 | } else { 67 | dt = DT; 68 | } 69 | 70 | for(;;){ 71 | /* Next/step function .*/ 72 | last_state = springIntegrateState( last_state || initState, dt ); 73 | /* Store the position. */ 74 | path.push( 1 + last_state.x ); 75 | time_lapsed += 16; 76 | /* If the change threshold is reached, break. */ 77 | if( !(Math.abs( last_state.x ) > tolerance && Math.abs( last_state.v ) > tolerance) ){ 78 | break; 79 | } 80 | } 81 | 82 | /* If duration is not defined, return the actual time required for completing this animation. Otherwise, return a closure that holds the 83 | computed path and returns a snapshot of the position according to a given percentComplete. */ 84 | return !have_duration ? time_lapsed : function( percentComplete ){ return path[ (percentComplete * (path.length - 1)) | 0 ]; }; 85 | }; 86 | }()); 87 | 88 | export default generateSpringRK4; 89 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/core/animation/start.js: -------------------------------------------------------------------------------- 1 | function startAnimation( self, ani, now, isCore ){ 2 | let ani_p = ani._private; 3 | 4 | ani_p.started = true; 5 | ani_p.startTime = now - ani_p.progress * ani_p.duration; 6 | } 7 | 8 | export default startAnimation; 9 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/core/animation/step-all.js: -------------------------------------------------------------------------------- 1 | import step from './step'; 2 | import startAnimation from './start'; 3 | 4 | function stepAll( now, cy ){ 5 | let eles = cy._private.aniEles; 6 | let doneEles = []; 7 | 8 | function stepOne( ele, isCore ){ 9 | let _p = ele._private; 10 | let current = _p.animation.current; 11 | let queue = _p.animation.queue; 12 | let ranAnis = false; 13 | 14 | // if nothing currently animating, get something from the queue 15 | if( current.length === 0 ){ 16 | let next = queue.shift(); 17 | 18 | if( next ){ 19 | current.push( next ); 20 | } 21 | } 22 | 23 | let callbacks = function( callbacks ){ 24 | for( let j = callbacks.length - 1; j >= 0; j-- ){ 25 | let cb = callbacks[ j ]; 26 | 27 | cb(); 28 | } 29 | 30 | callbacks.splice( 0, callbacks.length ); 31 | }; 32 | 33 | // step and remove if done 34 | for( let i = current.length - 1; i >= 0; i-- ){ 35 | let ani = current[ i ]; 36 | let ani_p = ani._private; 37 | 38 | if( ani_p.stopped ){ 39 | current.splice( i, 1 ); 40 | 41 | ani_p.hooked = false; 42 | ani_p.playing = false; 43 | ani_p.started = false; 44 | 45 | callbacks( ani_p.frames ); 46 | 47 | continue; 48 | } 49 | 50 | if( !ani_p.playing && !ani_p.applying ){ continue; } 51 | 52 | // an apply() while playing shouldn't do anything 53 | if( ani_p.playing && ani_p.applying ){ 54 | ani_p.applying = false; 55 | } 56 | 57 | if( !ani_p.started ){ 58 | startAnimation( ele, ani, now, isCore ); 59 | } 60 | 61 | step( ele, ani, now, isCore ); 62 | 63 | if( ani_p.applying ){ 64 | ani_p.applying = false; 65 | } 66 | 67 | callbacks( ani_p.frames ); 68 | 69 | if( ani_p.step != null ){ 70 | ani_p.step(now); 71 | } 72 | 73 | if( ani.completed() ){ 74 | current.splice( i, 1 ); 75 | 76 | ani_p.hooked = false; 77 | ani_p.playing = false; 78 | ani_p.started = false; 79 | 80 | callbacks( ani_p.completes ); 81 | } 82 | 83 | ranAnis = true; 84 | } 85 | 86 | if( !isCore && current.length === 0 && queue.length === 0 ){ 87 | doneEles.push( ele ); 88 | } 89 | 90 | return ranAnis; 91 | } // stepElement 92 | 93 | // handle all eles 94 | let ranEleAni = false; 95 | for( let e = 0; e < eles.length; e++ ){ 96 | let ele = eles[ e ]; 97 | let handledThisEle = stepOne( ele ); 98 | 99 | ranEleAni = ranEleAni || handledThisEle; 100 | } // each element 101 | 102 | let ranCoreAni = stepOne( cy, true ); 103 | 104 | // notify renderer 105 | if( ranEleAni || ranCoreAni ){ 106 | if( eles.length > 0 ){ 107 | cy.notify('draw', eles); 108 | } else { 109 | cy.notify('draw'); 110 | } 111 | } 112 | 113 | // remove elements from list of currently animating if its queues are empty 114 | eles.unmerge( doneEles ); 115 | 116 | cy.emit('step'); 117 | 118 | } // stepAll 119 | 120 | export default stepAll; 121 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/core/data.js: -------------------------------------------------------------------------------- 1 | import define from '../define'; 2 | 3 | const fn = { 4 | data: define.data( { 5 | field: 'data', 6 | bindingEvent: 'data', 7 | allowBinding: true, 8 | allowSetting: true, 9 | settingEvent: 'data', 10 | settingTriggersEvent: true, 11 | triggerFnName: 'trigger', 12 | allowGetting: true, 13 | updateStyle: true 14 | } ), 15 | 16 | removeData: define.removeData( { 17 | field: 'data', 18 | event: 'data', 19 | triggerFnName: 'trigger', 20 | triggerEvent: true, 21 | updateStyle: true 22 | } ), 23 | 24 | scratch: define.data( { 25 | field: 'scratch', 26 | bindingEvent: 'scratch', 27 | allowBinding: true, 28 | allowSetting: true, 29 | settingEvent: 'scratch', 30 | settingTriggersEvent: true, 31 | triggerFnName: 'trigger', 32 | allowGetting: true, 33 | updateStyle: true 34 | } ), 35 | 36 | removeScratch: define.removeData( { 37 | field: 'scratch', 38 | event: 'scratch', 39 | triggerFnName: 'trigger', 40 | triggerEvent: true, 41 | updateStyle: true 42 | } ) 43 | }; 44 | 45 | // aliases 46 | fn.attr = fn.data; 47 | fn.removeAttr = fn.removeData; 48 | 49 | export default fn; -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/core/events.js: -------------------------------------------------------------------------------- 1 | import Emitter from '../emitter'; 2 | import define from '../define'; 3 | import * as is from '../is'; 4 | import Selector from '../selector'; 5 | 6 | let emitterOptions = { 7 | qualifierCompare: function( selector1, selector2 ){ 8 | if( selector1 == null || selector2 == null ){ 9 | return selector1 == null && selector2 == null; 10 | } else { 11 | return selector1.sameText( selector2 ); 12 | } 13 | }, 14 | eventMatches: function( cy, listener, eventObj ){ 15 | let selector = listener.qualifier; 16 | 17 | if( selector != null ){ 18 | return cy !== eventObj.target && is.element( eventObj.target ) && selector.matches( eventObj.target ); 19 | } 20 | 21 | return true; 22 | }, 23 | addEventFields: function( cy, evt ){ 24 | evt.cy = cy; 25 | evt.target = cy; 26 | }, 27 | callbackContext: function( cy, listener, eventObj ){ 28 | return listener.qualifier != null ? eventObj.target : cy; 29 | } 30 | }; 31 | 32 | let argSelector = function( arg ){ 33 | if( is.string(arg) ){ 34 | return new Selector( arg ); 35 | } else { 36 | return arg; 37 | } 38 | }; 39 | 40 | let elesfn = ({ 41 | createEmitter: function(){ 42 | let _p = this._private; 43 | 44 | if( !_p.emitter ){ 45 | _p.emitter = new Emitter( emitterOptions, this ); 46 | } 47 | 48 | return this; 49 | }, 50 | 51 | emitter: function(){ 52 | return this._private.emitter; 53 | }, 54 | 55 | on: function( events, selector, callback ){ 56 | this.emitter().on( events, argSelector(selector), callback ); 57 | 58 | return this; 59 | }, 60 | 61 | removeListener: function( events, selector, callback ){ 62 | this.emitter().removeListener( events, argSelector(selector), callback ); 63 | 64 | return this; 65 | }, 66 | 67 | removeAllListeners: function(){ 68 | this.emitter().removeAllListeners(); 69 | 70 | return this; 71 | }, 72 | 73 | one: function( events, selector, callback ){ 74 | this.emitter().one( events, argSelector(selector), callback ); 75 | 76 | return this; 77 | }, 78 | 79 | once: function( events, selector, callback ){ 80 | this.emitter().one( events, argSelector(selector), callback ); 81 | 82 | return this; 83 | }, 84 | 85 | emit: function( events, extraParams ){ 86 | this.emitter().emit( events, extraParams ); 87 | 88 | return this; 89 | }, 90 | 91 | emitAndNotify: function( event, eles ){ 92 | this.emit( event ); 93 | 94 | this.notify( event, eles ); 95 | 96 | return this; 97 | } 98 | }); 99 | 100 | define.eventAliasesOn( elesfn ); 101 | 102 | export default elesfn; 103 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/core/export.js: -------------------------------------------------------------------------------- 1 | let corefn = ({ 2 | 3 | png: function( options ){ 4 | let renderer = this._private.renderer; 5 | options = options || {}; 6 | 7 | return renderer.png( options ); 8 | }, 9 | 10 | jpg: function( options ){ 11 | let renderer = this._private.renderer; 12 | options = options || {}; 13 | 14 | options.bg = options.bg || '#fff'; 15 | 16 | return renderer.jpg( options ); 17 | } 18 | 19 | }); 20 | 21 | corefn.jpeg = corefn.jpg; 22 | 23 | export default corefn; 24 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/core/layout.js: -------------------------------------------------------------------------------- 1 | import * as util from '../util'; 2 | import * as is from '../is'; 3 | 4 | let corefn = ({ 5 | 6 | layout: function( options ){ 7 | let cy = this; 8 | 9 | if( options == null ){ 10 | util.error( 'Layout options must be specified to make a layout' ); 11 | return; 12 | } 13 | 14 | if( options.name == null ){ 15 | util.error( 'A `name` must be specified to make a layout' ); 16 | return; 17 | } 18 | 19 | let name = options.name; 20 | let Layout = cy.extension( 'layout', name ); 21 | 22 | if( Layout == null ){ 23 | util.error( 'No such layout `' + name + '` found. Did you forget to import it and `cytoscape.use()` it?' ); 24 | return; 25 | } 26 | 27 | let eles; 28 | if( is.string( options.eles ) ){ 29 | eles = cy.$( options.eles ); 30 | } else { 31 | eles = options.eles != null ? options.eles : cy.$(); 32 | } 33 | 34 | let layout = new Layout( util.extend( {}, options, { 35 | cy: cy, 36 | eles: eles 37 | } ) ); 38 | 39 | return layout; 40 | } 41 | 42 | }); 43 | 44 | corefn.createLayout = corefn.makeLayout = corefn.layout; 45 | 46 | export default corefn; 47 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/core/notification.js: -------------------------------------------------------------------------------- 1 | let corefn = ({ 2 | notify: function( eventName, eventEles ){ 3 | let _p = this._private; 4 | 5 | if( this.batching() ){ 6 | _p.batchNotifications = _p.batchNotifications || {}; 7 | 8 | let eles = _p.batchNotifications[ eventName ] = _p.batchNotifications[ eventName ] || this.collection(); 9 | 10 | if( eventEles != null ){ 11 | eles.merge( eventEles ); 12 | } 13 | 14 | return; // notifications are disabled during batching 15 | } 16 | 17 | if( !_p.notificationsEnabled ){ return; } // exit on disabled 18 | 19 | let renderer = this.renderer(); 20 | 21 | // exit if destroy() called on core or renderer in between frames #1499 #1528 22 | if( this.destroyed() || !renderer ){ return; } 23 | 24 | renderer.notify( eventName, eventEles ); 25 | }, 26 | 27 | notifications: function( bool ){ 28 | let p = this._private; 29 | 30 | if( bool === undefined ){ 31 | return p.notificationsEnabled; 32 | } else { 33 | p.notificationsEnabled = bool ? true : false; 34 | } 35 | 36 | return this; 37 | }, 38 | 39 | noNotifications: function( callback ){ 40 | this.notifications( false ); 41 | callback(); 42 | this.notifications( true ); 43 | }, 44 | 45 | batching: function(){ 46 | return this._private.batchCount > 0; 47 | }, 48 | 49 | startBatch: function(){ 50 | let _p = this._private; 51 | 52 | if( _p.batchCount == null ){ 53 | _p.batchCount = 0; 54 | } 55 | 56 | if( _p.batchCount === 0 ){ 57 | _p.batchStyleEles = this.collection(); 58 | _p.batchNotifications = {}; 59 | } 60 | 61 | _p.batchCount++; 62 | 63 | return this; 64 | }, 65 | 66 | endBatch: function(){ 67 | let _p = this._private; 68 | 69 | if( _p.batchCount === 0 ){ return this; } 70 | 71 | _p.batchCount--; 72 | 73 | if( _p.batchCount === 0 ){ 74 | // update style for dirty eles 75 | _p.batchStyleEles.updateStyle(); 76 | 77 | let renderer = this.renderer(); 78 | 79 | // notify the renderer of queued eles and event types 80 | Object.keys( _p.batchNotifications ).forEach( eventName => { 81 | let eles = _p.batchNotifications[eventName]; 82 | 83 | if( eles.empty() ){ 84 | renderer.notify( eventName ); 85 | } else { 86 | renderer.notify( eventName, eles ); 87 | } 88 | } ); 89 | } 90 | 91 | return this; 92 | }, 93 | 94 | batch: function( callback ){ 95 | this.startBatch(); 96 | callback(); 97 | this.endBatch(); 98 | 99 | return this; 100 | }, 101 | 102 | // for backwards compatibility 103 | batchData: function( map ){ 104 | let cy = this; 105 | 106 | return this.batch( function(){ 107 | let ids = Object.keys( map ); 108 | 109 | for( let i = 0; i < ids.length; i++ ){ 110 | let id = ids[i]; 111 | let data = map[ id ]; 112 | let ele = cy.getElementById( id ); 113 | 114 | ele.data( data ); 115 | } 116 | } ); 117 | } 118 | }); 119 | 120 | export default corefn; 121 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/core/renderer.js: -------------------------------------------------------------------------------- 1 | import * as util from '../util'; 2 | 3 | let rendererDefaults = util.defaults({ 4 | hideEdgesOnViewport: false, 5 | textureOnViewport: false, 6 | motionBlur: false, 7 | motionBlurOpacity: 0.05, 8 | pixelRatio: undefined, 9 | desktopTapThreshold: 4, 10 | touchTapThreshold: 8, 11 | wheelSensitivity: 1, 12 | debug: false, 13 | showFps: false 14 | }); 15 | 16 | let corefn = ({ 17 | 18 | renderTo: function( context, zoom, pan, pxRatio ){ 19 | let r = this._private.renderer; 20 | 21 | r.renderTo( context, zoom, pan, pxRatio ); 22 | return this; 23 | }, 24 | 25 | renderer: function(){ 26 | return this._private.renderer; 27 | }, 28 | 29 | forceRender: function(){ 30 | this.notify('draw'); 31 | 32 | return this; 33 | }, 34 | 35 | resize: function(){ 36 | this.invalidateSize(); 37 | 38 | this.emitAndNotify('resize'); 39 | 40 | return this; 41 | }, 42 | 43 | initRenderer: function( options ){ 44 | let cy = this; 45 | 46 | let RendererProto = cy.extension( 'renderer', options.name ); 47 | if( RendererProto == null ){ 48 | util.error( `Can not initialise: No such renderer \`${options.name}\` found. Did you forget to import it and \`cytoscape.use()\` it?` ); 49 | return; 50 | } 51 | 52 | if( options.wheelSensitivity !== undefined ){ 53 | util.warn(`You have set a custom wheel sensitivity. This will make your app zoom unnaturally when using mainstream mice. You should change this value from the default only if you can guarantee that all your users will use the same hardware and OS configuration as your current machine.`); 54 | } 55 | 56 | let rOpts = rendererDefaults(options); 57 | 58 | rOpts.cy = cy; 59 | 60 | cy._private.renderer = new RendererProto( rOpts ); 61 | 62 | this.notify('init'); 63 | }, 64 | 65 | destroyRenderer: function(){ 66 | let cy = this; 67 | 68 | cy.notify('destroy'); // destroy the renderer 69 | 70 | let domEle = cy.container(); 71 | if( domEle ){ 72 | domEle._cyreg = null; 73 | 74 | while( domEle.childNodes.length > 0 ){ 75 | domEle.removeChild( domEle.childNodes[0] ); 76 | } 77 | } 78 | 79 | cy._private.renderer = null; // to be extra safe, remove the ref 80 | cy.mutableElements().forEach(function( ele ){ 81 | let _p = ele._private; 82 | _p.rscratch = {}; 83 | _p.rstyle = {}; 84 | _p.animation.current = []; 85 | _p.animation.queue = []; 86 | }); 87 | }, 88 | 89 | onRender: function( fn ){ 90 | return this.on('render', fn); 91 | }, 92 | 93 | offRender: function( fn ){ 94 | return this.off('render', fn); 95 | } 96 | 97 | }); 98 | 99 | corefn.invalidateDimensions = corefn.resize; 100 | 101 | export default corefn; 102 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/core/search.js: -------------------------------------------------------------------------------- 1 | import * as is from '../is'; 2 | import Collection from '../collection'; 3 | 4 | let corefn = ({ 5 | 6 | // get a collection 7 | // - empty collection on no args 8 | // - collection of elements in the graph on selector arg 9 | // - guarantee a returned collection when elements or collection specified 10 | collection: function( eles, opts ){ 11 | 12 | if( is.string( eles ) ){ 13 | return this.$( eles ); 14 | 15 | } else if( is.elementOrCollection( eles ) ){ 16 | return eles.collection(); 17 | 18 | } else if( is.array( eles ) ){ 19 | return new Collection( this, eles, opts ); 20 | } 21 | 22 | return new Collection( this ); 23 | }, 24 | 25 | nodes: function( selector ){ 26 | let nodes = this.$( function( ele ){ 27 | return ele.isNode(); 28 | } ); 29 | 30 | if( selector ){ 31 | return nodes.filter( selector ); 32 | } 33 | 34 | return nodes; 35 | }, 36 | 37 | edges: function( selector ){ 38 | let edges = this.$( function( ele ){ 39 | return ele.isEdge(); 40 | } ); 41 | 42 | if( selector ){ 43 | return edges.filter( selector ); 44 | } 45 | 46 | return edges; 47 | }, 48 | 49 | // search the graph like jQuery 50 | $: function( selector ){ 51 | let eles = this._private.elements; 52 | 53 | if( selector ){ 54 | return eles.filter( selector ); 55 | } else { 56 | return eles.spawnSelf(); 57 | } 58 | }, 59 | 60 | mutableElements: function(){ 61 | return this._private.elements; 62 | } 63 | 64 | }); 65 | 66 | // aliases 67 | corefn.elements = corefn.filter = corefn.$; 68 | 69 | export default corefn; 70 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/core/style.js: -------------------------------------------------------------------------------- 1 | import * as is from '../is'; 2 | import Style from '../style'; 3 | 4 | let corefn = ({ 5 | 6 | style: function( newStyle ){ 7 | if( newStyle ){ 8 | let s = this.setStyle( newStyle ); 9 | 10 | s.update(); 11 | } 12 | 13 | return this._private.style; 14 | }, 15 | 16 | setStyle: function( style ){ 17 | let _p = this._private; 18 | 19 | if( is.stylesheet( style ) ){ 20 | _p.style = style.generateStyle( this ); 21 | 22 | } else if( is.array( style ) ){ 23 | _p.style = Style.fromJson( this, style ); 24 | 25 | } else if( is.string( style ) ){ 26 | _p.style = Style.fromString( this, style ); 27 | 28 | } else { 29 | _p.style = Style( this ); 30 | } 31 | 32 | return _p.style; 33 | }, 34 | 35 | // e.g. cy.data() changed => recalc ele mappers 36 | updateStyle: function(){ 37 | this.mutableElements().updateStyle(); // just send to all eles 38 | } 39 | }); 40 | 41 | export default corefn; 42 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/define/events.js: -------------------------------------------------------------------------------- 1 | import Promise from '../promise'; 2 | 3 | let define = { 4 | 5 | eventAliasesOn: function( proto ){ 6 | let p = proto; 7 | 8 | p.addListener = p.listen = p.bind = p.on; 9 | p.unlisten = p.unbind = p.off = p.removeListener; 10 | p.trigger = p.emit; 11 | 12 | // this is just a wrapper alias of .on() 13 | p.pon = p.promiseOn = function( events, selector ){ 14 | let self = this; 15 | let args = Array.prototype.slice.call( arguments, 0 ); 16 | 17 | return new Promise( function( resolve, reject ){ 18 | let callback = function( e ){ 19 | self.off.apply( self, offArgs ); 20 | 21 | resolve( e ); 22 | }; 23 | 24 | let onArgs = args.concat( [ callback ] ); 25 | let offArgs = onArgs.concat( [] ); 26 | 27 | self.on.apply( self, onArgs ); 28 | } ); 29 | }; 30 | }, 31 | 32 | }; // define 33 | 34 | export default define; 35 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/define/index.js: -------------------------------------------------------------------------------- 1 | // use this module to cherry pick functions into your prototype 2 | // (useful for functions shared between the core and collections, for example) 3 | 4 | // e.g. 5 | // let foo = define.foo({ /* params... */ }) 6 | 7 | import * as util from '../util'; 8 | import animation from './animation'; 9 | import data from './data'; 10 | import events from './events'; 11 | 12 | let define = {}; 13 | 14 | [ 15 | animation, 16 | data, 17 | events 18 | ].forEach(function( m ){ 19 | util.assign( define, m ); 20 | }); 21 | 22 | export default define; 23 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/event.js: -------------------------------------------------------------------------------- 1 | /*! 2 | Event object based on jQuery events, MIT license 3 | 4 | https://jquery.org/license/ 5 | https://tldrlegal.com/license/mit-license 6 | https://github.com/jquery/jquery/blob/master/src/event.js 7 | */ 8 | 9 | let Event = function( src, props ){ 10 | this.recycle( src, props ); 11 | }; 12 | 13 | function returnFalse(){ 14 | return false; 15 | } 16 | 17 | function returnTrue(){ 18 | return true; 19 | } 20 | 21 | // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html 22 | Event.prototype = { 23 | instanceString: function(){ 24 | return 'event'; 25 | }, 26 | 27 | recycle: function( src, props ){ 28 | this.isImmediatePropagationStopped = this.isPropagationStopped = this.isDefaultPrevented = returnFalse; 29 | 30 | if( src != null && src.preventDefault ){ // Browser Event object 31 | this.type = src.type; 32 | 33 | // Events bubbling up the document may have been marked as prevented 34 | // by a handler lower down the tree; reflect the correct value. 35 | this.isDefaultPrevented = ( src.defaultPrevented ) ? returnTrue : returnFalse; 36 | 37 | } else if( src != null && src.type ){ // Plain object containing all event details 38 | props = src; 39 | 40 | } else { // Event string 41 | this.type = src; 42 | } 43 | 44 | // Put explicitly provided properties onto the event object 45 | if( props != null ){ 46 | // more efficient to manually copy fields we use 47 | this.originalEvent = props.originalEvent; 48 | this.type = props.type != null ? props.type : this.type; 49 | this.cy = props.cy; 50 | this.target = props.target; 51 | this.position = props.position; 52 | this.renderedPosition = props.renderedPosition; 53 | this.namespace = props.namespace; 54 | this.layout = props.layout; 55 | } 56 | 57 | if( this.cy != null && this.position != null && this.renderedPosition == null ){ 58 | // create a rendered position based on the passed position 59 | let pos = this.position; 60 | let zoom = this.cy.zoom(); 61 | let pan = this.cy.pan(); 62 | 63 | this.renderedPosition = { 64 | x: pos.x * zoom + pan.x, 65 | y: pos.y * zoom + pan.y 66 | }; 67 | } 68 | 69 | // Create a timestamp if incoming event doesn't have one 70 | this.timeStamp = src && src.timeStamp || Date.now(); 71 | }, 72 | 73 | preventDefault: function(){ 74 | this.isDefaultPrevented = returnTrue; 75 | 76 | let e = this.originalEvent; 77 | if( !e ){ 78 | return; 79 | } 80 | 81 | // if preventDefault exists run it on the original event 82 | if( e.preventDefault ){ 83 | e.preventDefault(); 84 | } 85 | }, 86 | 87 | stopPropagation: function(){ 88 | this.isPropagationStopped = returnTrue; 89 | 90 | let e = this.originalEvent; 91 | if( !e ){ 92 | return; 93 | } 94 | 95 | // if stopPropagation exists run it on the original event 96 | if( e.stopPropagation ){ 97 | e.stopPropagation(); 98 | } 99 | }, 100 | 101 | stopImmediatePropagation: function(){ 102 | this.isImmediatePropagationStopped = returnTrue; 103 | this.stopPropagation(); 104 | }, 105 | 106 | isDefaultPrevented: returnFalse, 107 | isPropagationStopped: returnFalse, 108 | isImmediatePropagationStopped: returnFalse 109 | }; 110 | 111 | export default Event; 112 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/extensions/index.js: -------------------------------------------------------------------------------- 1 | import layout from './layout'; 2 | import renderer from './renderer'; 3 | 4 | export default [ 5 | { 6 | type: 'layout', 7 | extensions: layout 8 | }, 9 | 10 | { 11 | type: 'renderer', 12 | extensions: renderer 13 | } 14 | ]; 15 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/extensions/layout/circle.js: -------------------------------------------------------------------------------- 1 | import * as util from '../../util'; 2 | import * as math from '../../math'; 3 | import * as is from '../../is'; 4 | 5 | let defaults = { 6 | fit: true, // whether to fit the viewport to the graph 7 | padding: 30, // the padding on fit 8 | boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h } 9 | avoidOverlap: true, // prevents node overlap, may overflow boundingBox and radius if not enough space 10 | nodeDimensionsIncludeLabels: false, // Excludes the label when calculating node bounding boxes for the layout algorithm 11 | spacingFactor: undefined, // Applies a multiplicative factor (>0) to expand or compress the overall area that the nodes take up 12 | radius: undefined, // the radius of the circle 13 | startAngle: 3 / 2 * Math.PI, // where nodes start in radians 14 | sweep: undefined, // how many radians should be between the first and last node (defaults to full circle) 15 | clockwise: true, // whether the layout should go clockwise (true) or counterclockwise/anticlockwise (false) 16 | sort: undefined, // a sorting function to order the nodes; e.g. function(a, b){ return a.data('weight') - b.data('weight') } 17 | animate: false, // whether to transition the node positions 18 | animationDuration: 500, // duration of animation in ms if enabled 19 | animationEasing: undefined, // easing of animation if enabled 20 | animateFilter: function ( node, i ){ return true; }, // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts 21 | ready: undefined, // callback on layoutready 22 | stop: undefined, // callback on layoutstop 23 | transform: function (node, position ){ return position; } // transform a given node position. Useful for changing flow direction in discrete layouts 24 | 25 | }; 26 | 27 | function CircleLayout( options ){ 28 | this.options = util.extend( {}, defaults, options ); 29 | } 30 | 31 | CircleLayout.prototype.run = function(){ 32 | let params = this.options; 33 | let options = params; 34 | 35 | let cy = params.cy; 36 | let eles = options.eles; 37 | 38 | let clockwise = options.counterclockwise !== undefined ? !options.counterclockwise : options.clockwise; 39 | 40 | let nodes = eles.nodes().not( ':parent' ); 41 | 42 | if( options.sort ){ 43 | nodes = nodes.sort( options.sort ); 44 | } 45 | 46 | let bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : { 47 | x1: 0, y1: 0, w: cy.width(), h: cy.height() 48 | } ); 49 | 50 | let center = { 51 | x: bb.x1 + bb.w / 2, 52 | y: bb.y1 + bb.h / 2 53 | }; 54 | 55 | let sweep = options.sweep === undefined ? 2 * Math.PI - 2 * Math.PI / nodes.length : options.sweep; 56 | let dTheta = sweep / ( Math.max( 1, nodes.length - 1 ) ); 57 | let r; 58 | 59 | let minDistance = 0; 60 | for( let i = 0; i < nodes.length; i++ ){ 61 | let n = nodes[ i ]; 62 | let nbb = n.layoutDimensions( options ); 63 | let w = nbb.w; 64 | let h = nbb.h; 65 | 66 | minDistance = Math.max( minDistance, w, h ); 67 | } 68 | 69 | if( is.number( options.radius ) ){ 70 | r = options.radius; 71 | } else if( nodes.length <= 1 ){ 72 | r = 0; 73 | } else { 74 | r = Math.min( bb.h, bb.w ) / 2 - minDistance; 75 | } 76 | 77 | // calculate the radius 78 | if( nodes.length > 1 && options.avoidOverlap ){ // but only if more than one node (can't overlap) 79 | minDistance *= 1.75; // just to have some nice spacing 80 | 81 | let dcos = Math.cos( dTheta ) - Math.cos( 0 ); 82 | let dsin = Math.sin( dTheta ) - Math.sin( 0 ); 83 | let rMin = Math.sqrt( minDistance * minDistance / ( dcos * dcos + dsin * dsin ) ); // s.t. no nodes overlapping 84 | r = Math.max( rMin, r ); 85 | } 86 | 87 | let getPos = function( ele, i ){ 88 | let theta = options.startAngle + i * dTheta * ( clockwise ? 1 : -1 ); 89 | 90 | let rx = r * Math.cos( theta ); 91 | let ry = r * Math.sin( theta ); 92 | let pos = { 93 | x: center.x + rx, 94 | y: center.y + ry 95 | }; 96 | 97 | return pos; 98 | }; 99 | 100 | eles.nodes().layoutPositions( this, options, getPos ); 101 | 102 | return this; // chaining 103 | }; 104 | 105 | export default CircleLayout; 106 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/extensions/layout/index.js: -------------------------------------------------------------------------------- 1 | import breadthfirstLayout from './breadthfirst'; 2 | import circleLayout from './circle'; 3 | import concentricLayout from './concentric'; 4 | import coseLayout from './cose'; 5 | import gridLayout from './grid'; 6 | import nullLayout from './null'; 7 | import presetLayout from './preset'; 8 | import randomLayout from './random'; 9 | 10 | export default [ 11 | { name: 'breadthfirst', impl: breadthfirstLayout }, 12 | { name: 'circle', impl: circleLayout }, 13 | { name: 'concentric',impl: concentricLayout }, 14 | { name: 'cose', impl: coseLayout }, 15 | { name: 'grid', impl: gridLayout }, 16 | { name: 'null', impl: nullLayout }, 17 | { name: 'preset', impl: presetLayout }, 18 | { name: 'random', impl: randomLayout } 19 | ]; 20 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/extensions/layout/null.js: -------------------------------------------------------------------------------- 1 | import * as util from '../../util'; 2 | 3 | // default layout options 4 | let defaults = { 5 | ready: function(){}, // on layoutready 6 | stop: function(){} // on layoutstop 7 | }; 8 | 9 | // constructor 10 | // options : object containing layout options 11 | function NullLayout( options ){ 12 | this.options = util.extend( {}, defaults, options ); 13 | } 14 | 15 | // runs the layout 16 | NullLayout.prototype.run = function(){ 17 | let options = this.options; 18 | let eles = options.eles; // elements to consider in the layout 19 | let layout = this; 20 | 21 | // cy is automatically populated for us in the constructor 22 | // (disable eslint for next line as this serves as example layout code to external developers) 23 | // eslint-disable-next-line no-unused-vars 24 | let cy = options.cy; 25 | 26 | layout.emit( 'layoutstart' ); 27 | 28 | // puts all nodes at (0, 0) 29 | // n.b. most layouts would use layoutPositions(), instead of positions() and manual events 30 | eles.nodes().positions( function(){ 31 | return { 32 | x: 0, 33 | y: 0 34 | }; 35 | } ); 36 | 37 | // trigger layoutready when each node has had its position set at least once 38 | layout.one( 'layoutready', options.ready ); 39 | layout.emit( 'layoutready' ); 40 | 41 | // trigger layoutstop when the layout stops (e.g. finishes) 42 | layout.one( 'layoutstop', options.stop ); 43 | layout.emit( 'layoutstop' ); 44 | 45 | return this; // chaining 46 | }; 47 | 48 | // called on continuous layouts to stop them before they finish 49 | NullLayout.prototype.stop = function(){ 50 | return this; // chaining 51 | }; 52 | 53 | export default NullLayout; 54 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/extensions/layout/preset.js: -------------------------------------------------------------------------------- 1 | import * as util from '../../util'; 2 | import * as is from '../../is'; 3 | import { copyPosition } from '../../math'; 4 | 5 | let defaults = { 6 | positions: undefined, // map of (node id) => (position obj); or function(node){ return somPos; } 7 | zoom: undefined, // the zoom level to set (prob want fit = false if set) 8 | pan: undefined, // the pan level to set (prob want fit = false if set) 9 | fit: true, // whether to fit to viewport 10 | padding: 30, // padding on fit 11 | animate: false, // whether to transition the node positions 12 | animationDuration: 500, // duration of animation in ms if enabled 13 | animationEasing: undefined, // easing of animation if enabled 14 | animateFilter: function ( node, i ){ return true; }, // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts 15 | ready: undefined, // callback on layoutready 16 | stop: undefined, // callback on layoutstop 17 | transform: function (node, position ){ return position; } // transform a given node position. Useful for changing flow direction in discrete layouts 18 | }; 19 | 20 | function PresetLayout( options ){ 21 | this.options = util.extend( {}, defaults, options ); 22 | } 23 | 24 | PresetLayout.prototype.run = function(){ 25 | let options = this.options; 26 | let eles = options.eles; 27 | 28 | let nodes = eles.nodes(); 29 | let posIsFn = is.fn( options.positions ); 30 | 31 | function getPosition( node ){ 32 | if( options.positions == null ){ 33 | return copyPosition( node.position() ); 34 | } 35 | 36 | if( posIsFn ){ 37 | return options.positions( node ); 38 | } 39 | 40 | let pos = options.positions[ node._private.data.id ]; 41 | 42 | if( pos == null ){ 43 | return null; 44 | } 45 | 46 | return pos; 47 | } 48 | 49 | nodes.layoutPositions( this, options, function( node, i ){ 50 | let position = getPosition( node ); 51 | 52 | if( node.locked() || position == null ){ 53 | return false; 54 | } 55 | 56 | return position; 57 | } ); 58 | 59 | return this; // chaining 60 | }; 61 | 62 | export default PresetLayout; 63 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/extensions/layout/random.js: -------------------------------------------------------------------------------- 1 | import * as util from '../../util'; 2 | import * as math from '../../math'; 3 | 4 | let defaults = { 5 | fit: true, // whether to fit to viewport 6 | padding: 30, // fit padding 7 | boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h } 8 | animate: false, // whether to transition the node positions 9 | animationDuration: 500, // duration of animation in ms if enabled 10 | animationEasing: undefined, // easing of animation if enabled 11 | animateFilter: function ( node, i ){ return true; }, // a function that determines whether the node should be animated. All nodes animated by default on animate enabled. Non-animated nodes are positioned immediately when the layout starts 12 | ready: undefined, // callback on layoutready 13 | stop: undefined, // callback on layoutstop 14 | transform: function (node, position ){ return position; } // transform a given node position. Useful for changing flow direction in discrete layouts 15 | }; 16 | 17 | function RandomLayout( options ){ 18 | this.options = util.extend( {}, defaults, options ); 19 | } 20 | 21 | RandomLayout.prototype.run = function(){ 22 | let options = this.options; 23 | let cy = options.cy; 24 | let eles = options.eles; 25 | 26 | 27 | let bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : { 28 | x1: 0, y1: 0, w: cy.width(), h: cy.height() 29 | } ); 30 | 31 | let getPos = function( node, i ){ 32 | return { 33 | x: bb.x1 + Math.round( Math.random() * bb.w ), 34 | y: bb.y1 + Math.round( Math.random() * bb.h ) 35 | }; 36 | }; 37 | 38 | eles.nodes().layoutPositions( this, options, getPos ); 39 | 40 | return this; // chaining 41 | }; 42 | 43 | export default RandomLayout; 44 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/extensions/renderer/base/coord-ele-math/edge-projection.js: -------------------------------------------------------------------------------- 1 | import * as math from '../../../../math'; 2 | 3 | var BRp = {}; 4 | 5 | function pushBezierPts( r, edge, pts ){ 6 | var qbezierAt = function( p1, p2, p3, t ){ return math.qbezierAt( p1, p2, p3, t ); }; 7 | var _p = edge._private; 8 | var bpts = _p.rstyle.bezierPts; 9 | 10 | for( var i = 0; i < r.bezierProjPcts.length; i++ ){ 11 | var p = r.bezierProjPcts[i]; 12 | 13 | bpts.push( { 14 | x: qbezierAt( pts[0], pts[2], pts[4], p ), 15 | y: qbezierAt( pts[1], pts[3], pts[5], p ) 16 | } ); 17 | } 18 | } 19 | 20 | BRp.storeEdgeProjections = function( edge ){ 21 | var _p = edge._private; 22 | var rs = _p.rscratch; 23 | var et = rs.edgeType; 24 | 25 | // clear the cached points state 26 | _p.rstyle.bezierPts = null; 27 | _p.rstyle.linePts = null; 28 | _p.rstyle.haystackPts = null; 29 | 30 | if( et === 'multibezier' || et === 'bezier' || et === 'self' || et === 'compound' ){ 31 | _p.rstyle.bezierPts = []; 32 | 33 | for( var i = 0; i + 5 < rs.allpts.length; i += 4 ){ 34 | pushBezierPts( this, edge, rs.allpts.slice( i, i + 6 ) ); 35 | } 36 | } else if( et === 'segments' ){ 37 | var lpts = _p.rstyle.linePts = []; 38 | 39 | for( var i = 0; i + 1 < rs.allpts.length; i += 2 ){ 40 | lpts.push( { 41 | x: rs.allpts[ i ], 42 | y: rs.allpts[ i + 1] 43 | } ); 44 | } 45 | } else if( et === 'haystack' ){ 46 | var hpts = rs.haystackPts; 47 | 48 | _p.rstyle.haystackPts = [ 49 | { x: hpts[0], y: hpts[1] }, 50 | { x: hpts[2], y: hpts[3] } 51 | ]; 52 | } 53 | 54 | _p.rstyle.arrowWidth = this.getArrowWidth( edge.pstyle('width').pfValue, edge.pstyle( 'arrow-scale' ).value ) 55 | * this.arrowShapeWidth; 56 | }; 57 | 58 | BRp.recalculateEdgeProjections = function( edges ){ 59 | this.findEdgeControlPoints( edges ); 60 | }; 61 | 62 | export default BRp; 63 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/extensions/renderer/base/coord-ele-math/index.js: -------------------------------------------------------------------------------- 1 | import * as util from '../../../../util'; 2 | 3 | import coords from './coords'; 4 | import edgeArrows from './edge-arrows'; 5 | import edgeControlPoints from './edge-control-points'; 6 | import edgeEndpoints from './edge-endpoints'; 7 | import edgeProjection from './edge-projection'; 8 | import labels from './labels'; 9 | import nodes from './nodes'; 10 | import renderedStyle from './rendered-style'; 11 | import zOrdering from './z-ordering'; 12 | 13 | var BRp = {}; 14 | 15 | [ 16 | coords, 17 | edgeArrows, 18 | edgeControlPoints, 19 | edgeEndpoints, 20 | edgeProjection, 21 | labels, 22 | nodes, 23 | renderedStyle, 24 | zOrdering 25 | ].forEach(function( props ){ 26 | util.extend( BRp, props ); 27 | }); 28 | 29 | export default BRp; 30 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/extensions/renderer/base/coord-ele-math/nodes.js: -------------------------------------------------------------------------------- 1 | var BRp = {}; 2 | 3 | import { warn } from '../../../../util'; 4 | 5 | const TOO_SMALL_CUT_RECT = 28; 6 | 7 | let warnedCutRect = false; 8 | 9 | BRp.getNodeShape = function( node ){ 10 | var r = this; 11 | var shape = node.pstyle( 'shape' ).value; 12 | 13 | if( shape === 'cutrectangle' && (node.width() < TOO_SMALL_CUT_RECT || node.height() < TOO_SMALL_CUT_RECT) ){ 14 | if( !warnedCutRect ){ 15 | warn('The `cutrectangle` node shape can not be used at small sizes so `rectangle` is used instead'); 16 | 17 | warnedCutRect = true; 18 | } 19 | 20 | return 'rectangle'; 21 | } 22 | 23 | if( node.isParent() ){ 24 | if( shape === 'rectangle' 25 | || shape === 'roundrectangle' 26 | || shape === 'round-rectangle' 27 | || shape === 'cutrectangle' 28 | || shape === 'cut-rectangle' 29 | || shape === 'barrel' ){ 30 | return shape; 31 | } else { 32 | return 'rectangle'; 33 | } 34 | } 35 | 36 | if( shape === 'polygon' ){ 37 | var points = node.pstyle( 'shape-polygon-points' ).value; 38 | 39 | return r.nodeShapes.makePolygon( points ).name; 40 | } 41 | 42 | return shape; 43 | }; 44 | 45 | export default BRp; 46 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/extensions/renderer/base/coord-ele-math/z-ordering.js: -------------------------------------------------------------------------------- 1 | import zIndexSort from '../../../../collection/zsort'; 2 | 3 | var BRp = {}; 4 | 5 | BRp.updateCachedGrabbedEles = function(){ 6 | var eles = this.cachedZSortedEles; 7 | 8 | if( !eles ){ 9 | // just let this be recalculated on the next z sort tick 10 | return; 11 | } 12 | 13 | eles.drag = []; 14 | eles.nondrag = []; 15 | 16 | var grabTargets = []; 17 | 18 | for( var i = 0; i < eles.length; i++ ){ 19 | var ele = eles[i]; 20 | var rs = ele._private.rscratch; 21 | 22 | if( ele.grabbed() && !ele.isParent() ){ 23 | grabTargets.push( ele ); 24 | } else if( rs.inDragLayer ){ 25 | eles.drag.push( ele ); 26 | } else { 27 | eles.nondrag.push( ele ); 28 | } 29 | } 30 | 31 | // put the grab target nodes last so it's on top of its neighbourhood 32 | for( var i = 0; i < grabTargets.length; i++ ){ 33 | var ele = grabTargets[i]; 34 | 35 | eles.drag.push( ele ); 36 | } 37 | }; 38 | 39 | BRp.invalidateCachedZSortedEles = function(){ 40 | this.cachedZSortedEles = null; 41 | }; 42 | 43 | BRp.getCachedZSortedEles = function( forceRecalc ){ 44 | if( forceRecalc || !this.cachedZSortedEles ){ 45 | var eles = this.cy.mutableElements().toArray(); 46 | 47 | eles.sort( zIndexSort ); 48 | 49 | eles.interactive = eles.filter(ele => ele.interactive()); 50 | 51 | this.cachedZSortedEles = eles; 52 | 53 | this.updateCachedGrabbedEles(); 54 | } else { 55 | eles = this.cachedZSortedEles; 56 | } 57 | 58 | return eles; 59 | }; 60 | 61 | export default BRp; 62 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/extensions/renderer/base/images.js: -------------------------------------------------------------------------------- 1 | var BRp = {}; 2 | 3 | BRp.getCachedImage = function( url, crossOrigin, onLoad ){ 4 | var r = this; 5 | var imageCache = r.imageCache = r.imageCache || {}; 6 | var cache = imageCache[ url ]; 7 | 8 | if( cache ){ 9 | if( !cache.image.complete ){ 10 | cache.image.addEventListener('load', onLoad); 11 | } 12 | 13 | return cache.image; 14 | } else { 15 | cache = imageCache[ url ] = imageCache[ url ] || {}; 16 | 17 | var image = cache.image = new Image(); // eslint-disable-line no-undef 18 | 19 | image.addEventListener('load', onLoad); 20 | image.addEventListener('error', function(){ image.error = true; }); 21 | 22 | // #1582 safari doesn't load data uris with crossOrigin properly 23 | // https://bugs.webkit.org/show_bug.cgi?id=123978 24 | var dataUriPrefix = 'data:'; 25 | var isDataUri = url.substring( 0, dataUriPrefix.length ).toLowerCase() === dataUriPrefix; 26 | if( !isDataUri ){ 27 | image.crossOrigin = crossOrigin; // prevent tainted canvas 28 | } 29 | 30 | image.src = url; 31 | 32 | return image; 33 | } 34 | }; 35 | 36 | export default BRp; 37 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/extensions/renderer/base/redraw.js: -------------------------------------------------------------------------------- 1 | import * as util from '../../../util'; 2 | 3 | var BRp = {}; 4 | 5 | BRp.timeToRender = function(){ 6 | return this.redrawTotalTime / this.redrawCount; 7 | }; 8 | 9 | BRp.redraw = function( options ){ 10 | options = options || util.staticEmptyObject(); 11 | 12 | var r = this; 13 | 14 | if( r.averageRedrawTime === undefined ){ r.averageRedrawTime = 0; } 15 | if( r.lastRedrawTime === undefined ){ r.lastRedrawTime = 0; } 16 | if( r.lastDrawTime === undefined ){ r.lastDrawTime = 0; } 17 | 18 | r.requestedFrame = true; 19 | r.renderOptions = options; 20 | }; 21 | 22 | BRp.beforeRender = function( fn, priority ){ 23 | // the renderer can't add tick callbacks when destroyed 24 | if( this.destroyed ){ return; } 25 | 26 | if( priority == null ){ 27 | util.error('Priority is not optional for beforeRender'); 28 | } 29 | 30 | var cbs = this.beforeRenderCallbacks; 31 | 32 | cbs.push({ fn: fn, priority: priority }); 33 | 34 | // higher priority callbacks executed first 35 | cbs.sort(function( a, b ){ return b.priority - a.priority; }); 36 | }; 37 | 38 | var beforeRenderCallbacks = function( r, willDraw, startTime ){ 39 | var cbs = r.beforeRenderCallbacks; 40 | 41 | for( var i = 0; i < cbs.length; i++ ){ 42 | cbs[i].fn( willDraw, startTime ); 43 | } 44 | }; 45 | 46 | BRp.startRenderLoop = function(){ 47 | var r = this; 48 | var cy = r.cy; 49 | 50 | if( r.renderLoopStarted ){ 51 | return; 52 | } else { 53 | r.renderLoopStarted = true; 54 | } 55 | 56 | var renderFn = function( requestTime ){ 57 | if( r.destroyed ){ return; } 58 | 59 | if( cy.batching() ){ 60 | // mid-batch, none of these should run 61 | // - pre frame hooks (calculations, texture caches, style, etc.) 62 | // - any drawing 63 | } else if( r.requestedFrame && !r.skipFrame ){ 64 | beforeRenderCallbacks( r, true, requestTime ); 65 | 66 | var startTime = util.performanceNow(); 67 | 68 | r.render( r.renderOptions ); 69 | 70 | var endTime = r.lastDrawTime = util.performanceNow(); 71 | 72 | if( r.averageRedrawTime === undefined ){ 73 | r.averageRedrawTime = endTime - startTime; 74 | } 75 | 76 | if( r.redrawCount === undefined ){ 77 | r.redrawCount = 0; 78 | } 79 | 80 | r.redrawCount++; 81 | 82 | if( r.redrawTotalTime === undefined ){ 83 | r.redrawTotalTime = 0; 84 | } 85 | 86 | var duration = endTime - startTime; 87 | 88 | r.redrawTotalTime += duration; 89 | r.lastRedrawTime = duration; 90 | 91 | // use a weighted average with a bias from the previous average so we don't spike so easily 92 | r.averageRedrawTime = r.averageRedrawTime / 2 + duration / 2; 93 | 94 | r.requestedFrame = false; 95 | } else { 96 | beforeRenderCallbacks( r, false, requestTime ); 97 | } 98 | 99 | r.skipFrame = false; 100 | 101 | util.requestAnimationFrame( renderFn ); 102 | }; 103 | 104 | util.requestAnimationFrame( renderFn ); 105 | 106 | }; 107 | 108 | export default BRp; 109 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/extensions/renderer/canvas/arrow-shapes.js: -------------------------------------------------------------------------------- 1 | var CRp = {}; 2 | 3 | var impl; 4 | 5 | function polygon( context, points ){ 6 | for( var i = 0; i < points.length; i++ ){ 7 | var pt = points[ i ]; 8 | 9 | context.lineTo( pt.x, pt.y ); 10 | } 11 | } 12 | 13 | function triangleBackcurve( context, points, controlPoint ){ 14 | var firstPt; 15 | 16 | for( var i = 0; i < points.length; i++ ){ 17 | var pt = points[ i ]; 18 | 19 | if( i === 0 ){ 20 | firstPt = pt; 21 | } 22 | 23 | context.lineTo( pt.x, pt.y ); 24 | } 25 | 26 | context.quadraticCurveTo( controlPoint.x, controlPoint.y, firstPt.x, firstPt.y ); 27 | } 28 | 29 | function triangleTee( context, trianglePoints, teePoints ){ 30 | if( context.beginPath ){ context.beginPath(); } 31 | 32 | var triPts = trianglePoints; 33 | for( var i = 0; i < triPts.length; i++ ){ 34 | var pt = triPts[ i ]; 35 | 36 | context.lineTo( pt.x, pt.y ); 37 | } 38 | 39 | var teePts = teePoints; 40 | var firstTeePt = teePoints[0]; 41 | context.moveTo( firstTeePt.x, firstTeePt.y ); 42 | 43 | for( var i = 1; i < teePts.length; i++ ){ 44 | var pt = teePts[ i ]; 45 | 46 | context.lineTo( pt.x, pt.y ); 47 | } 48 | 49 | if( context.closePath ){ context.closePath(); } 50 | } 51 | 52 | function circleTriangle(context, trianglePoints, rx, ry, r) { 53 | if (context.beginPath) { context.beginPath(); } 54 | context.arc(rx, ry, r, 0, Math.PI * 2, false); 55 | var triPts = trianglePoints; 56 | var firstTrPt = triPts[0]; 57 | context.moveTo(firstTrPt.x, firstTrPt.y); 58 | for (var i = 0; i < triPts.length; i++) { 59 | var pt = triPts[i]; 60 | context.lineTo(pt.x, pt.y); 61 | } 62 | if (context.closePath) { 63 | context.closePath(); 64 | } 65 | } 66 | 67 | function circle( context, rx, ry, r ){ 68 | context.arc( rx, ry, r, 0, Math.PI * 2, false ); 69 | } 70 | 71 | CRp.arrowShapeImpl = function( name ){ 72 | return ( impl || (impl = { 73 | 'polygon': polygon, 74 | 75 | 'triangle-backcurve': triangleBackcurve, 76 | 77 | 'triangle-tee': triangleTee, 78 | 79 | 'circle-triangle' : circleTriangle, 80 | 81 | 'triangle-cross': triangleTee, 82 | 83 | 'circle': circle 84 | }) )[ name ]; 85 | }; 86 | 87 | export default CRp; -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/extensions/renderer/canvas/node-shapes.js: -------------------------------------------------------------------------------- 1 | var CRp = {}; 2 | 3 | CRp.nodeShapeImpl = function( name, context, centerX, centerY, width, height, points ){ 4 | switch( name ){ 5 | case 'ellipse': 6 | return this.drawEllipsePath( context, centerX, centerY, width, height ); 7 | case 'polygon': 8 | return this.drawPolygonPath( context, centerX, centerY, width, height, points ); 9 | case 'round-polygon': 10 | return this.drawRoundPolygonPath(context, centerX, centerY, width, height, points ); 11 | case 'roundrectangle': 12 | case 'round-rectangle': 13 | return this.drawRoundRectanglePath( context, centerX, centerY, width, height ); 14 | case 'cutrectangle': 15 | case 'cut-rectangle': 16 | return this.drawCutRectanglePath( context, centerX, centerY, width, height ); 17 | case 'bottomroundrectangle': 18 | case 'bottom-round-rectangle': 19 | return this.drawBottomRoundRectanglePath( context, centerX, centerY, width, height ); 20 | case 'barrel': 21 | return this.drawBarrelPath( context, centerX, centerY, width, height ); 22 | } 23 | }; 24 | 25 | export default CRp; 26 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/extensions/renderer/canvas/texture-cache-defs.js: -------------------------------------------------------------------------------- 1 | import * as util from '../../../util'; 2 | 3 | var fullFpsTime = 1000/60; // assume 60 frames per second 4 | 5 | export default { 6 | setupDequeueing: function( opts ){ 7 | return function setupDequeueingImpl(){ 8 | var self = this; 9 | var r = this.renderer; 10 | 11 | if( self.dequeueingSetup ){ 12 | return; 13 | } else { 14 | self.dequeueingSetup = true; 15 | } 16 | 17 | var queueRedraw = util.debounce( function(){ 18 | r.redrawHint( 'eles', true ); 19 | r.redrawHint( 'drag', true ); 20 | 21 | r.redraw(); 22 | }, opts.deqRedrawThreshold ); 23 | 24 | var dequeue = function( willDraw, frameStartTime ){ 25 | var startTime = util.performanceNow(); 26 | var avgRenderTime = r.averageRedrawTime; 27 | var renderTime = r.lastRedrawTime; 28 | var deqd = []; 29 | var extent = r.cy.extent(); 30 | var pixelRatio = r.getPixelRatio(); 31 | 32 | // if we aren't in a tick that causes a draw, then the rendered style 33 | // queue won't automatically be flushed before dequeueing starts 34 | if( !willDraw ){ 35 | r.flushRenderedStyleQueue(); 36 | } 37 | 38 | while( true ){ // eslint-disable-line no-constant-condition 39 | var now = util.performanceNow(); 40 | var duration = now - startTime; 41 | var frameDuration = now - frameStartTime; 42 | 43 | if( renderTime < fullFpsTime ){ 44 | // if we're rendering faster than the ideal fps, then do dequeueing 45 | // during all of the remaining frame time 46 | 47 | var timeAvailable = fullFpsTime - ( willDraw ? avgRenderTime : 0 ); 48 | 49 | if( frameDuration >= opts.deqFastCost * timeAvailable ){ 50 | break; 51 | } 52 | } else { 53 | if( willDraw ){ 54 | if( 55 | duration >= opts.deqCost * renderTime 56 | || duration >= opts.deqAvgCost * avgRenderTime 57 | ){ 58 | break; 59 | } 60 | } else if( frameDuration >= opts.deqNoDrawCost * fullFpsTime ){ 61 | break; 62 | } 63 | } 64 | 65 | var thisDeqd = opts.deq( self, pixelRatio, extent ); 66 | 67 | if( thisDeqd.length > 0 ){ 68 | for( var i = 0; i < thisDeqd.length; i++ ){ 69 | deqd.push( thisDeqd[i] ); 70 | } 71 | } else { 72 | break; 73 | } 74 | } 75 | 76 | // callbacks on dequeue 77 | if( deqd.length > 0 ){ 78 | opts.onDeqd( self, deqd ); 79 | 80 | if( !willDraw && opts.shouldRedraw( self, deqd, pixelRatio, extent ) ){ 81 | queueRedraw(); 82 | } 83 | } 84 | }; 85 | 86 | var priority = opts.priority || util.noop; 87 | 88 | r.beforeRender( dequeue, priority( self ) ); 89 | }; 90 | } 91 | }; 92 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/extensions/renderer/index.js: -------------------------------------------------------------------------------- 1 | import nullRenderer from './null'; 2 | import baseRenderer from './base'; 3 | import canvasRenderer from './canvas'; 4 | 5 | export default [ 6 | { name: 'null', impl: nullRenderer }, 7 | { name: 'base', impl: baseRenderer }, 8 | { name: 'canvas', impl: canvasRenderer } 9 | ]; 10 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/extensions/renderer/null/index.js: -------------------------------------------------------------------------------- 1 | function NullRenderer( options ){ 2 | this.options = options; 3 | this.notifications = 0; // for testing 4 | } 5 | 6 | let noop = function(){}; 7 | 8 | let throwImgErr = function(){ 9 | throw new Error('A headless instance can not render images'); 10 | }; 11 | 12 | NullRenderer.prototype = { 13 | recalculateRenderedStyle: noop, 14 | notify: function(){ this.notifications++; }, 15 | init: noop, 16 | isHeadless: function(){ return true; }, 17 | png: throwImgErr, 18 | jpg: throwImgErr 19 | }; 20 | 21 | export default NullRenderer; 22 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/heap.js: -------------------------------------------------------------------------------- 1 | export { default } from 'heap'; 2 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/index.js: -------------------------------------------------------------------------------- 1 | import * as is from './is'; 2 | import Core from './core'; 3 | import extension from './extension'; 4 | import Stylesheet from './stylesheet'; 5 | import version from './version'; 6 | import { warnings } from './util'; 7 | 8 | let cytoscape = function( options ){ 9 | // if no options specified, use default 10 | if( options === undefined ){ 11 | options = {}; 12 | } 13 | 14 | // create instance 15 | if( is.plainObject( options ) ){ 16 | return new Core( options ); 17 | } 18 | 19 | // allow for registration of extensions 20 | else if( is.string( options ) ){ 21 | return extension.apply( extension, arguments ); 22 | } 23 | }; 24 | 25 | // e.g. cytoscape.use( require('cytoscape-foo'), bar ) 26 | cytoscape.use = function( ext ){ 27 | let args = Array.prototype.slice.call( arguments, 1 ); // args to pass to ext 28 | 29 | args.unshift( cytoscape ); // cytoscape is first arg to ext 30 | 31 | ext.apply( null, args ); 32 | 33 | return this; 34 | }; 35 | 36 | cytoscape.warnings = function(bool){ 37 | return warnings(bool); 38 | }; 39 | 40 | // replaced by build system 41 | cytoscape.version = version; 42 | 43 | // expose public apis (mostly for extensions) 44 | cytoscape.stylesheet = cytoscape.Stylesheet = Stylesheet; 45 | 46 | export default cytoscape; 47 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/map.js: -------------------------------------------------------------------------------- 1 | /* global Map */ 2 | 3 | class ObjectMap { 4 | constructor(){ 5 | this._obj = {}; 6 | } 7 | 8 | set( key, val ){ 9 | this._obj[ key ] = val; 10 | 11 | return this; 12 | } 13 | 14 | delete( key ){ 15 | this._obj[ key ] = undefined; 16 | 17 | return this; 18 | } 19 | 20 | clear(){ 21 | this._obj = {}; 22 | } 23 | 24 | has( key ){ 25 | return this._obj[ key ] !== undefined; 26 | } 27 | 28 | get( key ){ 29 | return this._obj[ key ]; 30 | } 31 | } 32 | 33 | export default typeof Map !== 'undefined' ? Map : ObjectMap; 34 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/selector/data.js: -------------------------------------------------------------------------------- 1 | import * as is from '../is'; 2 | 3 | export const valCmp = (fieldVal, operator, value) => { 4 | let matches; 5 | let isFieldStr = is.string( fieldVal ); 6 | let isFieldNum = is.number( fieldVal ); 7 | let isValStr = is.string(value); 8 | let fieldStr, valStr; 9 | let caseInsensitive = false; 10 | let notExpr = false; 11 | let isIneqCmp = false; 12 | 13 | if( operator.indexOf( '!' ) >= 0 ){ 14 | operator = operator.replace( '!', '' ); 15 | notExpr = true; 16 | } 17 | 18 | if( operator.indexOf( '@' ) >= 0 ){ 19 | operator = operator.replace( '@', '' ); 20 | caseInsensitive = true; 21 | } 22 | 23 | if( isFieldStr || isValStr || caseInsensitive ){ 24 | fieldStr = !isFieldStr && !isFieldNum ? '' : '' + fieldVal; 25 | valStr = '' + value; 26 | } 27 | 28 | // if we're doing a case insensitive comparison, then we're using a STRING comparison 29 | // even if we're comparing numbers 30 | if( caseInsensitive ){ 31 | fieldVal = fieldStr = fieldStr.toLowerCase(); 32 | value = valStr = valStr.toLowerCase(); 33 | } 34 | 35 | switch( operator ){ 36 | case '*=': 37 | matches = fieldStr.indexOf( valStr ) >= 0; 38 | break; 39 | case '$=': 40 | matches = fieldStr.indexOf( valStr, fieldStr.length - valStr.length ) >= 0; 41 | break; 42 | case '^=': 43 | matches = fieldStr.indexOf( valStr ) === 0; 44 | break; 45 | case '=': 46 | matches = fieldVal === value; 47 | break; 48 | case '>': 49 | isIneqCmp = true; 50 | matches = fieldVal > value; 51 | break; 52 | case '>=': 53 | isIneqCmp = true; 54 | matches = fieldVal >= value; 55 | break; 56 | case '<': 57 | isIneqCmp = true; 58 | matches = fieldVal < value; 59 | break; 60 | case '<=': 61 | isIneqCmp = true; 62 | matches = fieldVal <= value; 63 | break; 64 | default: 65 | matches = false; 66 | break; 67 | } 68 | 69 | // apply the not op, but null vals for inequalities should always stay non-matching 70 | if( notExpr && ( fieldVal != null || !isIneqCmp ) ){ 71 | matches = !matches; 72 | } 73 | 74 | return matches; 75 | }; 76 | 77 | export const boolCmp = (fieldVal, operator) => { 78 | switch( operator ){ 79 | case '?': 80 | return fieldVal ? true : false; 81 | case '!': 82 | return fieldVal ? false : true; 83 | case '^': 84 | return fieldVal === undefined; 85 | } 86 | }; 87 | 88 | export const existCmp = (fieldVal) => fieldVal !== undefined; 89 | 90 | export const data = (ele, field) => ele.data(field); 91 | 92 | export const meta = (ele, field) => ele[field](); -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/selector/index.js: -------------------------------------------------------------------------------- 1 | import * as is from '../is'; 2 | import * as util from '../util'; 3 | 4 | import parse from './parse'; 5 | import matching from './matching'; 6 | import Type from './type'; 7 | 8 | let Selector = function( selector ){ 9 | this.inputText = selector; 10 | this.currentSubject = null; 11 | this.compoundCount = 0; 12 | this.edgeCount = 0; 13 | this.length = 0; 14 | 15 | if( selector == null || ( is.string( selector ) && selector.match( /^\s*$/ ) ) ){ 16 | // leave empty 17 | 18 | } else if( is.elementOrCollection( selector ) ){ 19 | 20 | this.addQuery({ 21 | checks: [ { 22 | type: Type.COLLECTION, 23 | value: selector.collection() 24 | } ] 25 | }); 26 | 27 | } else if( is.fn( selector ) ){ 28 | 29 | this.addQuery({ 30 | checks: [ { 31 | type: Type.FILTER, 32 | value: selector 33 | } ] 34 | }); 35 | 36 | } else if( is.string( selector ) ){ 37 | if( !this.parse( selector ) ){ 38 | this.invalid = true; 39 | } 40 | 41 | } else { 42 | util.error( 'A selector must be created from a string; found ', selector ); 43 | } 44 | }; 45 | 46 | let selfn = Selector.prototype; 47 | 48 | [ 49 | parse, 50 | matching 51 | ].forEach( p => util.assign( selfn, p ) ); 52 | 53 | selfn.text = function(){ 54 | return this.inputText; 55 | }; 56 | 57 | selfn.size = function(){ 58 | return this.length; 59 | }; 60 | 61 | selfn.eq = function( i ){ 62 | return this[ i ]; 63 | }; 64 | 65 | selfn.sameText = function( otherSel ){ 66 | return !this.invalid && !otherSel.invalid && this.text() === otherSel.text(); 67 | }; 68 | 69 | selfn.addQuery = function( q ){ 70 | this[ this.length++ ] = q; 71 | }; 72 | 73 | selfn.selector = selfn.toString; 74 | 75 | export default Selector; 76 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/selector/matching.js: -------------------------------------------------------------------------------- 1 | import { matches as queryMatches } from './query-type-match'; 2 | import Type from './type'; 3 | 4 | // filter an existing collection 5 | let filter = function( collection ){ 6 | let self = this; 7 | 8 | // for 1 id #foo queries, just get the element 9 | if( self.length === 1 && self[0].checks.length === 1 && self[0].checks[0].type === Type.ID ){ 10 | return collection.getElementById( self[0].checks[0].value ).collection(); 11 | } 12 | 13 | let selectorFunction = function( element ){ 14 | for( let j = 0; j < self.length; j++ ){ 15 | let query = self[ j ]; 16 | 17 | if( queryMatches( query, element ) ){ 18 | return true; 19 | } 20 | } 21 | 22 | return false; 23 | }; 24 | 25 | if( self.text() == null ){ 26 | selectorFunction = function(){ return true; }; 27 | } 28 | 29 | return collection.filter( selectorFunction ); 30 | }; // filter 31 | 32 | // does selector match a single element? 33 | let matches = function( ele ){ 34 | let self = this; 35 | 36 | for( let j = 0; j < self.length; j++ ){ 37 | let query = self[ j ]; 38 | 39 | if( queryMatches( query, ele ) ){ 40 | return true; 41 | } 42 | } 43 | 44 | return false; 45 | }; // matches 46 | 47 | export default { matches, filter }; 48 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/selector/new-query.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Make a new query object 3 | * 4 | * @prop type {Type} The type enum (int) of the query 5 | * @prop checks List of checks to make against an ele to test for a match 6 | */ 7 | let newQuery = function(){ 8 | return { 9 | checks: [] 10 | }; 11 | }; 12 | 13 | export default newQuery; 14 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/selector/query-type-match.js: -------------------------------------------------------------------------------- 1 | import Type from './type'; 2 | import { stateSelectorMatches } from './state'; 3 | import { valCmp, boolCmp, existCmp, meta, data } from './data'; 4 | 5 | /** A lookup of `match(check, ele)` functions by `Type` int */ 6 | export const match = []; 7 | 8 | /** 9 | * Returns whether the query matches for the element 10 | * @param query The `{ type, value, ... }` query object 11 | * @param ele The element to compare against 12 | */ 13 | export const matches = (query, ele) => { 14 | return query.checks.every( chk => match[chk.type](chk, ele) ); 15 | }; 16 | 17 | match[Type.GROUP] = (check, ele) => { 18 | let group = check.value; 19 | 20 | return group === '*' || group === ele.group(); 21 | }; 22 | 23 | match[Type.STATE] = (check, ele) => { 24 | let stateSelector = check.value; 25 | 26 | return stateSelectorMatches( stateSelector, ele ); 27 | }; 28 | 29 | match[Type.ID] = (check, ele) => { 30 | let id = check.value; 31 | 32 | return ele.id() === id; 33 | }; 34 | 35 | match[Type.CLASS] = (check, ele) => { 36 | let cls = check.value; 37 | 38 | return ele.hasClass(cls); 39 | }; 40 | 41 | match[Type.META_COMPARE] = (check, ele) => { 42 | let { field, operator, value } = check; 43 | 44 | return valCmp( meta(ele, field), operator, value ); 45 | }; 46 | 47 | match[Type.DATA_COMPARE] = (check, ele) => { 48 | let { field, operator, value } = check; 49 | 50 | return valCmp( data(ele, field), operator, value ); 51 | }; 52 | 53 | match[Type.DATA_BOOL] = (check, ele) => { 54 | let { field, operator } = check; 55 | 56 | return boolCmp( data(ele, field), operator ); 57 | }; 58 | 59 | match[Type.DATA_EXIST] = (check, ele) => { 60 | let { field, operator } = check; 61 | 62 | return existCmp( data(ele, field), operator ); 63 | }; 64 | 65 | match[Type.UNDIRECTED_EDGE] = (check, ele) => { 66 | let qA = check.nodes[0]; 67 | let qB = check.nodes[1]; 68 | let src = ele.source(); 69 | let tgt = ele.target(); 70 | 71 | return ( matches(qA, src) && matches(qB, tgt) ) || ( matches(qB, src) && matches(qA, tgt) ); 72 | }; 73 | 74 | match[Type.NODE_NEIGHBOR] = (check, ele) => { 75 | return matches(check.node, ele) && ele.neighborhood().some( n => n.isNode() && matches(check.neighbor, n) ); 76 | }; 77 | 78 | match[Type.DIRECTED_EDGE] = (check, ele) => { 79 | return matches(check.source, ele.source()) && matches(check.target, ele.target()); 80 | }; 81 | 82 | match[Type.NODE_SOURCE] = (check, ele) => { 83 | return matches(check.source, ele) && ele.outgoers().some( n => n.isNode() && matches(check.target, n) ); 84 | }; 85 | 86 | match[Type.NODE_TARGET] = (check, ele) => { 87 | return matches(check.target, ele) && ele.incomers().some( n => n.isNode() && matches(check.source, n) ); 88 | }; 89 | 90 | match[Type.CHILD] = (check, ele) => { 91 | return matches(check.child, ele) && matches(check.parent, ele.parent()); 92 | }; 93 | 94 | match[Type.PARENT] = (check, ele) => { 95 | return matches(check.parent, ele) && ele.children().some( c => matches(check.child, c) ); 96 | }; 97 | 98 | match[Type.DESCENDANT] = (check, ele) => { 99 | return matches(check.descendant, ele) && ele.ancestors().some( a => matches(check.ancestor, a) ); 100 | }; 101 | 102 | match[Type.ANCESTOR] = (check, ele) => { 103 | return matches(check.ancestor, ele) && ele.descendants().some( d => matches(check.descendant, d) ); 104 | }; 105 | 106 | match[Type.COMPOUND_SPLIT] = (check, ele) => { 107 | return matches(check.subject, ele) && matches(check.left, ele) && matches(check.right, ele); 108 | }; 109 | 110 | match[Type.TRUE] = () => true; 111 | 112 | match[Type.COLLECTION] = (check, ele) => { 113 | let collection = check.value; 114 | 115 | return collection.has(ele); 116 | }; 117 | 118 | match[Type.FILTER] = (check, ele) => { 119 | let filter = check.value; 120 | 121 | return filter(ele); 122 | }; -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/selector/state.js: -------------------------------------------------------------------------------- 1 | import * as util from '../util'; 2 | 3 | export const stateSelectors = [ 4 | { 5 | selector: ':selected', 6 | matches: function( ele ){ return ele.selected(); } 7 | }, 8 | { 9 | selector: ':unselected', 10 | matches: function( ele ){ return !ele.selected(); } 11 | }, 12 | { 13 | selector: ':selectable', 14 | matches: function( ele ){ return ele.selectable(); } 15 | }, 16 | { 17 | selector: ':unselectable', 18 | matches: function( ele ){ return !ele.selectable(); } 19 | }, 20 | { 21 | selector: ':locked', 22 | matches: function( ele ){ return ele.locked(); } 23 | }, 24 | { 25 | selector: ':unlocked', 26 | matches: function( ele ){ return !ele.locked(); } 27 | }, 28 | { 29 | selector: ':visible', 30 | matches: function( ele ){ return ele.visible(); } 31 | }, 32 | { 33 | selector: ':hidden', 34 | matches: function( ele ){ return !ele.visible(); } 35 | }, 36 | { 37 | selector: ':transparent', 38 | matches: function( ele ){ return ele.transparent(); } 39 | }, 40 | { 41 | selector: ':grabbed', 42 | matches: function( ele ){ return ele.grabbed(); } 43 | }, 44 | { 45 | selector: ':free', 46 | matches: function( ele ){ return !ele.grabbed(); } 47 | }, 48 | { 49 | selector: ':removed', 50 | matches: function( ele ){ return ele.removed(); } 51 | }, 52 | { 53 | selector: ':inside', 54 | matches: function( ele ){ return !ele.removed(); } 55 | }, 56 | { 57 | selector: ':grabbable', 58 | matches: function( ele ){ return ele.grabbable(); } 59 | }, 60 | { 61 | selector: ':ungrabbable', 62 | matches: function( ele ){ return !ele.grabbable(); } 63 | }, 64 | { 65 | selector: ':animated', 66 | matches: function( ele ){ return ele.animated(); } 67 | }, 68 | { 69 | selector: ':unanimated', 70 | matches: function( ele ){ return !ele.animated(); } 71 | }, 72 | { 73 | selector: ':parent', 74 | matches: function( ele ){ return ele.isParent(); } 75 | }, 76 | { 77 | selector: ':childless', 78 | matches: function( ele ){ return ele.isChildless(); } 79 | }, 80 | { 81 | selector: ':child', 82 | matches: function( ele ){ return ele.isChild(); } 83 | }, 84 | { 85 | selector: ':orphan', 86 | matches: function( ele ){ return ele.isOrphan(); } 87 | }, 88 | { 89 | selector: ':nonorphan', 90 | matches: function( ele ){ return ele.isChild(); } 91 | }, 92 | { 93 | selector: ':compound', 94 | matches: function( ele ){ 95 | if( ele.isNode() ){ 96 | return ele.isParent(); 97 | } else { 98 | return ele.source().isParent() || ele.target().isParent(); 99 | } 100 | } 101 | }, 102 | { 103 | selector: ':loop', 104 | matches: function( ele ){ return ele.isLoop(); } 105 | }, 106 | { 107 | selector: ':simple', 108 | matches: function( ele ){ return ele.isSimple(); } 109 | }, 110 | { 111 | selector: ':active', 112 | matches: function( ele ){ return ele.active(); } 113 | }, 114 | { 115 | selector: ':inactive', 116 | matches: function( ele ){ return !ele.active(); } 117 | }, 118 | { 119 | selector: ':backgrounding', 120 | matches: function( ele ){ return ele.backgrounding(); } 121 | }, 122 | { 123 | selector: ':nonbackgrounding', 124 | matches: function( ele ){ return !ele.backgrounding(); } 125 | } 126 | ].sort(function( a, b ){ // n.b. selectors that are starting substrings of others must have the longer ones first 127 | return util.sort.descending( a.selector, b.selector ); 128 | }); 129 | 130 | let lookup = (function(){ 131 | let selToFn = {}; 132 | let s; 133 | 134 | for( let i = 0; i < stateSelectors.length; i++ ){ 135 | s = stateSelectors[i]; 136 | 137 | selToFn[ s.selector ] = s.matches; 138 | } 139 | 140 | return selToFn; 141 | })(); 142 | 143 | export const stateSelectorMatches = function( sel, ele ){ 144 | return lookup[ sel ]( ele ); 145 | }; 146 | 147 | export const stateSelectorRegex = '(' + stateSelectors.map(s => s.selector).join('|') + ')'; 148 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/selector/tokens.js: -------------------------------------------------------------------------------- 1 | import * as util from '../util'; 2 | 3 | // tokens in the query language 4 | const tokens = { 5 | metaChar: '[\\!\\"\\#\\$\\%\\&\\\'\\(\\)\\*\\+\\,\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\]\\^\\`\\{\\|\\}\\~]', // chars we need to escape in let names, etc 6 | comparatorOp: '=|\\!=|>|>=|<|<=|\\$=|\\^=|\\*=', // binary comparison op (used in data selectors) 7 | boolOp: '\\?|\\!|\\^', // boolean (unary) operators (used in data selectors) 8 | string: '"(?:\\\\"|[^"])*"' + '|' + "'(?:\\\\'|[^'])*'", // string literals (used in data selectors) -- doublequotes | singlequotes 9 | number: util.regex.number, // number literal (used in data selectors) --- e.g. 0.1234, 1234, 12e123 10 | meta: 'degree|indegree|outdegree', // allowed metadata fields (i.e. allowed functions to use from Collection) 11 | separator: '\\s*,\\s*', // queries are separated by commas, e.g. edge[foo = 'bar'], node.someClass 12 | descendant: '\\s+', 13 | child: '\\s+>\\s+', 14 | subject: '\\$', 15 | group: 'node|edge|\\*', 16 | directedEdge: '\\s+->\\s+', 17 | undirectedEdge: '\\s+<->\\s+' 18 | }; 19 | tokens.variable = '(?:[\\w-.]|(?:\\\\' + tokens.metaChar + '))+'; // a variable name can have letters, numbers, dashes, and periods 20 | tokens.className = '(?:[\\w-]|(?:\\\\' + tokens.metaChar + '))+'; // a class name has the same rules as a variable except it can't have a '.' in the name 21 | tokens.value = tokens.string + '|' + tokens.number; // a value literal, either a string or number 22 | tokens.id = tokens.variable; // an element id (follows variable conventions) 23 | 24 | (function(){ 25 | let ops, op, i; 26 | 27 | // add @ variants to comparatorOp 28 | ops = tokens.comparatorOp.split( '|' ); 29 | for( i = 0; i < ops.length; i++ ){ 30 | op = ops[ i ]; 31 | tokens.comparatorOp += '|@' + op; 32 | } 33 | 34 | // add ! variants to comparatorOp 35 | ops = tokens.comparatorOp.split( '|' ); 36 | for( i = 0; i < ops.length; i++ ){ 37 | op = ops[ i ]; 38 | 39 | if( op.indexOf( '!' ) >= 0 ){ continue; } // skip ops that explicitly contain ! 40 | if( op === '=' ){ continue; } // skip = b/c != is explicitly defined 41 | 42 | tokens.comparatorOp += '|\\!' + op; 43 | } 44 | })(); 45 | 46 | export default tokens; 47 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/selector/type.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A check type enum-like object. Uses integer values for fast match() lookup. 3 | * The ordering does not matter as long as the ints are unique. 4 | */ 5 | const Type = { 6 | /** E.g. node */ 7 | GROUP: 0, 8 | 9 | /** A collection of elements */ 10 | COLLECTION: 1, 11 | 12 | /** A filter(ele) function */ 13 | FILTER: 2, 14 | 15 | /** E.g. [foo > 1] */ 16 | DATA_COMPARE: 3, 17 | 18 | /** E.g. [foo] */ 19 | DATA_EXIST: 4, 20 | 21 | /** E.g. [?foo] */ 22 | DATA_BOOL: 5, 23 | 24 | /** E.g. [[degree > 2]] */ 25 | META_COMPARE: 6, 26 | 27 | /** E.g. :selected */ 28 | STATE: 7, 29 | 30 | /** E.g. #foo */ 31 | ID: 8, 32 | 33 | /** E.g. .foo */ 34 | CLASS: 9, 35 | 36 | /** E.g. #foo <-> #bar */ 37 | UNDIRECTED_EDGE: 10, 38 | 39 | /** E.g. #foo -> #bar */ 40 | DIRECTED_EDGE: 11, 41 | 42 | /** E.g. $#foo -> #bar */ 43 | NODE_SOURCE: 12, 44 | 45 | /** E.g. #foo -> $#bar */ 46 | NODE_TARGET: 13, 47 | 48 | /** E.g. $#foo <-> #bar */ 49 | NODE_NEIGHBOR: 14, 50 | 51 | /** E.g. #foo > #bar */ 52 | CHILD: 15, 53 | 54 | /** E.g. #foo #bar */ 55 | DESCENDANT: 16, 56 | 57 | /** E.g. $#foo > #bar */ 58 | PARENT: 17, 59 | 60 | /** E.g. $#foo #bar */ 61 | ANCESTOR: 18, 62 | 63 | /** E.g. #foo > $bar > #baz */ 64 | COMPOUND_SPLIT: 19, 65 | 66 | /** Always matches, useful placeholder for subject in `COMPOUND_SPLIT` */ 67 | TRUE: 20 68 | }; 69 | 70 | export default Type; -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/set.js: -------------------------------------------------------------------------------- 1 | /* global Set */ 2 | 3 | const undef = typeof undefined; 4 | 5 | class ObjectSet { 6 | constructor( arrayOrObjectSet ){ 7 | this._obj = Object.create(null); 8 | this.size = 0; 9 | 10 | if( arrayOrObjectSet != null ){ 11 | let arr; 12 | 13 | if( arrayOrObjectSet.instanceString != null && arrayOrObjectSet.instanceString() === this.instanceString() ){ 14 | arr = arrayOrObjectSet.toArray(); 15 | } else { 16 | arr = arrayOrObjectSet; 17 | } 18 | 19 | for( let i = 0; i < arr.length; i++ ){ 20 | this.add( arr[i] ); 21 | } 22 | } 23 | } 24 | 25 | instanceString(){ 26 | return 'set'; 27 | } 28 | 29 | add( val ){ 30 | let o = this._obj; 31 | 32 | if( o[ val ] !== 1 ){ 33 | o[ val ] = 1; 34 | this.size++; 35 | } 36 | } 37 | 38 | delete( val ){ 39 | let o = this._obj; 40 | 41 | if( o[ val ] === 1 ){ 42 | o[ val ] = 0; 43 | this.size--; 44 | } 45 | } 46 | 47 | clear(){ 48 | this._obj = Object.create(null); 49 | } 50 | 51 | has( val ){ 52 | return this._obj[ val ] === 1; 53 | } 54 | 55 | toArray(){ 56 | return Object.keys( this._obj ).filter( key => this.has(key) ); 57 | } 58 | 59 | forEach( callback, thisArg ){ 60 | return this.toArray().forEach( callback, thisArg ); 61 | } 62 | } 63 | 64 | export default typeof Set !== undef ? Set : ObjectSet; 65 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/style/container.js: -------------------------------------------------------------------------------- 1 | import window from '../window'; 2 | 3 | let styfn = {}; 4 | 5 | // gets what an em size corresponds to in pixels relative to a dom element 6 | styfn.getEmSizeInPixels = function(){ 7 | let px = this.containerCss( 'font-size' ); 8 | 9 | if( px != null ){ 10 | return parseFloat( px ); 11 | } else { 12 | return 1; // for headless 13 | } 14 | }; 15 | 16 | // gets css property from the core container 17 | styfn.containerCss = function( propName ){ 18 | let cy = this._private.cy; 19 | let domElement = cy.container(); 20 | 21 | if( window && domElement && window.getComputedStyle ){ 22 | return window.getComputedStyle( domElement ).getPropertyValue( propName ); 23 | } 24 | }; 25 | 26 | export default styfn; 27 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/style/json.js: -------------------------------------------------------------------------------- 1 | let styfn = {}; 2 | 3 | styfn.appendFromJson = function( json ){ 4 | let style = this; 5 | 6 | for( let i = 0; i < json.length; i++ ){ 7 | let context = json[ i ]; 8 | let selector = context.selector; 9 | let props = context.style || context.css; 10 | let names = Object.keys( props ); 11 | 12 | style.selector( selector ); // apply selector 13 | 14 | for( let j = 0; j < names.length; j++ ){ 15 | let name = names[j]; 16 | let value = props[ name ]; 17 | 18 | style.css( name, value ); // apply property 19 | } 20 | } 21 | 22 | return style; 23 | }; 24 | 25 | // accessible cy.style() function 26 | styfn.fromJson = function( json ){ 27 | let style = this; 28 | 29 | style.resetToDefault(); 30 | style.appendFromJson( json ); 31 | 32 | return style; 33 | }; 34 | 35 | // get json from cy.style() api 36 | styfn.json = function(){ 37 | let json = []; 38 | 39 | for( let i = this.defaultLength; i < this.length; i++ ){ 40 | let cxt = this[ i ]; 41 | let selector = cxt.selector; 42 | let props = cxt.properties; 43 | let css = {}; 44 | 45 | for( let j = 0; j < props.length; j++ ){ 46 | let prop = props[ j ]; 47 | css[ prop.name ] = prop.strValue; 48 | } 49 | 50 | json.push( { 51 | selector: !selector ? 'core' : selector.toString(), 52 | style: css 53 | } ); 54 | } 55 | 56 | return json; 57 | }; 58 | 59 | export default styfn; 60 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/style/string-sheet.js: -------------------------------------------------------------------------------- 1 | import * as util from '../util'; 2 | import Selector from '../selector'; 3 | 4 | let styfn = {}; 5 | 6 | styfn.appendFromString = function( string ){ 7 | let self = this; 8 | let style = this; 9 | let remaining = '' + string; 10 | let selAndBlockStr; 11 | let blockRem; 12 | let propAndValStr; 13 | 14 | // remove comments from the style string 15 | remaining = remaining.replace( /[/][*](\s|.)+?[*][/]/g, '' ); 16 | 17 | function removeSelAndBlockFromRemaining(){ 18 | // remove the parsed selector and block from the remaining text to parse 19 | if( remaining.length > selAndBlockStr.length ){ 20 | remaining = remaining.substr( selAndBlockStr.length ); 21 | } else { 22 | remaining = ''; 23 | } 24 | } 25 | 26 | function removePropAndValFromRem(){ 27 | // remove the parsed property and value from the remaining block text to parse 28 | if( blockRem.length > propAndValStr.length ){ 29 | blockRem = blockRem.substr( propAndValStr.length ); 30 | } else { 31 | blockRem = ''; 32 | } 33 | } 34 | 35 | for(;;){ 36 | let nothingLeftToParse = remaining.match( /^\s*$/ ); 37 | if( nothingLeftToParse ){ break; } 38 | 39 | let selAndBlock = remaining.match( /^\s*((?:.|\s)+?)\s*\{((?:.|\s)+?)\}/ ); 40 | 41 | if( !selAndBlock ){ 42 | util.warn( 'Halting stylesheet parsing: String stylesheet contains more to parse but no selector and block found in: ' + remaining ); 43 | break; 44 | } 45 | 46 | selAndBlockStr = selAndBlock[0]; 47 | 48 | // parse the selector 49 | let selectorStr = selAndBlock[1]; 50 | if( selectorStr !== 'core' ){ 51 | let selector = new Selector( selectorStr ); 52 | if( selector.invalid ){ 53 | util.warn( 'Skipping parsing of block: Invalid selector found in string stylesheet: ' + selectorStr ); 54 | 55 | // skip this selector and block 56 | removeSelAndBlockFromRemaining(); 57 | continue; 58 | } 59 | } 60 | 61 | // parse the block of properties and values 62 | let blockStr = selAndBlock[2]; 63 | let invalidBlock = false; 64 | blockRem = blockStr; 65 | let props = []; 66 | 67 | for(;;){ 68 | let nothingLeftToParse = blockRem.match( /^\s*$/ ); 69 | if( nothingLeftToParse ){ break; } 70 | 71 | let propAndVal = blockRem.match( /^\s*(.+?)\s*:\s*(.+?)\s*;/ ); 72 | 73 | if( !propAndVal ){ 74 | util.warn( 'Skipping parsing of block: Invalid formatting of style property and value definitions found in:' + blockStr ); 75 | invalidBlock = true; 76 | break; 77 | } 78 | 79 | propAndValStr = propAndVal[0]; 80 | let propStr = propAndVal[1]; 81 | let valStr = propAndVal[2]; 82 | 83 | let prop = self.properties[ propStr ]; 84 | if( !prop ){ 85 | util.warn( 'Skipping property: Invalid property name in: ' + propAndValStr ); 86 | 87 | // skip this property in the block 88 | removePropAndValFromRem(); 89 | continue; 90 | } 91 | 92 | let parsedProp = style.parse( propStr, valStr ); 93 | 94 | if( !parsedProp ){ 95 | util.warn( 'Skipping property: Invalid property definition in: ' + propAndValStr ); 96 | 97 | // skip this property in the block 98 | removePropAndValFromRem(); 99 | continue; 100 | } 101 | 102 | props.push( { 103 | name: propStr, 104 | val: valStr 105 | } ); 106 | removePropAndValFromRem(); 107 | } 108 | 109 | if( invalidBlock ){ 110 | removeSelAndBlockFromRemaining(); 111 | break; 112 | } 113 | 114 | // put the parsed block in the style 115 | style.selector( selectorStr ); 116 | for( let i = 0; i < props.length; i++ ){ 117 | let prop = props[ i ]; 118 | style.css( prop.name, prop.val ); 119 | } 120 | 121 | removeSelAndBlockFromRemaining(); 122 | } 123 | 124 | return style; 125 | }; 126 | 127 | styfn.fromString = function( string ){ 128 | let style = this; 129 | 130 | style.resetToDefault(); 131 | style.appendFromString( string ); 132 | 133 | return style; 134 | }; 135 | 136 | export default styfn; 137 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/stylesheet.js: -------------------------------------------------------------------------------- 1 | import * as is from './is'; 2 | import Style from './style'; 3 | import { dash2camel } from './util'; 4 | 5 | // a dummy stylesheet object that doesn't need a reference to the core 6 | // (useful for init) 7 | let Stylesheet = function(){ 8 | if( !(this instanceof Stylesheet) ){ 9 | return new Stylesheet(); 10 | } 11 | 12 | this.length = 0; 13 | }; 14 | 15 | let sheetfn = Stylesheet.prototype; 16 | 17 | sheetfn.instanceString = function(){ 18 | return 'stylesheet'; 19 | }; 20 | 21 | // just store the selector to be parsed later 22 | sheetfn.selector = function( selector ){ 23 | let i = this.length++; 24 | 25 | this[ i ] = { 26 | selector: selector, 27 | properties: [] 28 | }; 29 | 30 | return this; // chaining 31 | }; 32 | 33 | // just store the property to be parsed later 34 | sheetfn.css = function( name, value ){ 35 | let i = this.length - 1; 36 | 37 | if( is.string( name ) ){ 38 | this[ i ].properties.push( { 39 | name: name, 40 | value: value 41 | } ); 42 | } else if( is.plainObject( name ) ){ 43 | let map = name; 44 | let propNames = Object.keys( map ); 45 | 46 | for( let j = 0; j < propNames.length; j++ ){ 47 | let key = propNames[ j ]; 48 | let mapVal = map[ key ]; 49 | 50 | if( mapVal == null ){ continue; } 51 | 52 | let prop = Style.properties[key] || Style.properties[dash2camel(key)]; 53 | 54 | if( prop == null ){ continue; } 55 | 56 | let name = prop.name; 57 | let value = mapVal; 58 | 59 | this[ i ].properties.push( { 60 | name: name, 61 | value: value 62 | } ); 63 | } 64 | } 65 | 66 | return this; // chaining 67 | }; 68 | 69 | sheetfn.style = sheetfn.css; 70 | 71 | // generate a real style object from the dummy stylesheet 72 | sheetfn.generateStyle = function( cy ){ 73 | let style = new Style( cy ); 74 | 75 | return this.appendToStyle( style ); 76 | }; 77 | 78 | // append a dummy stylesheet object on a real style object 79 | sheetfn.appendToStyle = function( style ){ 80 | for( let i = 0; i < this.length; i++ ){ 81 | let context = this[ i ]; 82 | let selector = context.selector; 83 | let props = context.properties; 84 | 85 | style.selector( selector ); // apply selector 86 | 87 | for( let j = 0; j < props.length; j++ ){ 88 | let prop = props[ j ]; 89 | 90 | style.css( prop.name, prop.value ); // apply property 91 | } 92 | } 93 | 94 | return style; 95 | }; 96 | 97 | export default Stylesheet; 98 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/test.js: -------------------------------------------------------------------------------- 1 | /* 2 | This file tells the Mocha tests what build of Cytoscape to use. 3 | */ 4 | 5 | // For Travis or manual build tests, use the CJS build 6 | // NB : Must do `npm run build:cjs` before `npm test` 7 | if( process.env.TRAVIS || process.env.TEST_BUILD ){ 8 | module.exports = require('../build/cytoscape.cjs.js'); 9 | 10 | // Otherwise use the unbundled, unbabelified, raw source 11 | // NB : Must use a version of Node that natively supports all JS features used in the lib 12 | } else { 13 | module.exports = require('./index.js').default; 14 | } 15 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/util/extend.js: -------------------------------------------------------------------------------- 1 | export const extend = Object.assign != null ? Object.assign.bind( Object ) : function( tgt ){ 2 | let args = arguments; 3 | 4 | for( let i = 1; i < args.length; i++ ){ 5 | let obj = args[ i ]; 6 | 7 | if( obj == null ){ continue; } 8 | 9 | let keys = Object.keys( obj ); 10 | 11 | for( let j = 0; j < keys.length; j++ ){ 12 | let k = keys[j]; 13 | 14 | tgt[ k ] = obj[ k ]; 15 | } 16 | } 17 | 18 | return tgt; 19 | }; 20 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/util/hash.js: -------------------------------------------------------------------------------- 1 | export const DEFAULT_HASH_SEED = 9261; 2 | const K = 65599; // 37 also works pretty well 3 | export const DEFAULT_HASH_SEED_ALT = 5381; 4 | 5 | export const hashIterableInts = function( iterator, seed = DEFAULT_HASH_SEED ){ // sdbm/string-hash 6 | let hash = seed; 7 | let entry; 8 | 9 | for( ;; ){ 10 | entry = iterator.next(); 11 | 12 | if( entry.done ){ break; } 13 | 14 | hash = ((hash * K) + entry.value) | 0; 15 | } 16 | 17 | return hash; 18 | }; 19 | 20 | export const hashInt = function( num, seed = DEFAULT_HASH_SEED ){ // sdbm/string-hash 21 | return ((seed * K) + num) | 0; 22 | }; 23 | 24 | export const hashIntAlt = function( num, seed = DEFAULT_HASH_SEED_ALT ){ // djb2/string-hash 25 | return ((seed << 5) + seed + num) | 0; 26 | }; 27 | 28 | export const combineHashes = function(hash1, hash2){ 29 | return hash1 * 0x200000 + hash2; 30 | }; 31 | 32 | export const combineHashesArray = function(hashes){ 33 | return hashes[0] * 0x200000 + hashes[1]; 34 | }; 35 | 36 | export const hashArrays = function(hashes1, hashes2){ 37 | return [ 38 | hashInt(hashes1[0], hashes2[0]), 39 | hashIntAlt(hashes1[1], hashes2[1]) 40 | ]; 41 | }; 42 | 43 | export const hashIntsArray = function( ints, seed ){ 44 | let entry = { value: 0, done: false }; 45 | let i = 0; 46 | let length = ints.length; 47 | 48 | let iterator = { 49 | next(){ 50 | if( i < length ){ 51 | entry.value = ints[i++]; 52 | } else { 53 | entry.done = true; 54 | } 55 | 56 | return entry; 57 | } 58 | }; 59 | 60 | return hashIterableInts( iterator, seed ); 61 | }; 62 | 63 | export const hashString = function( str, seed ){ 64 | let entry = { value: 0, done: false }; 65 | let i = 0; 66 | let length = str.length; 67 | 68 | let iterator = { 69 | next(){ 70 | if( i < length ){ 71 | entry.value = str.charCodeAt(i++); 72 | } else { 73 | entry.done = true; 74 | } 75 | 76 | return entry; 77 | } 78 | }; 79 | 80 | return hashIterableInts( iterator, seed ); 81 | }; 82 | 83 | export const hashStrings = function(){ 84 | return hashStringsArray( arguments ); 85 | }; 86 | 87 | export const hashStringsArray = function( strs ){ 88 | let hash; 89 | 90 | for( let i = 0; i < strs.length; i++ ){ 91 | let str = strs[i]; 92 | 93 | if( i === 0 ){ 94 | hash = hashString( str ); 95 | } else { 96 | hash = hashString( str, hash ); 97 | } 98 | } 99 | 100 | return hash; 101 | }; 102 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/util/maps.js: -------------------------------------------------------------------------------- 1 | import * as is from '../is'; 2 | import { extend } from './extend'; 3 | 4 | // has anything been set in the map 5 | export const mapEmpty = map => { 6 | let empty = true; 7 | 8 | if( map != null ){ 9 | return Object.keys( map ).length === 0; 10 | } 11 | 12 | return empty; 13 | }; 14 | 15 | // pushes to the array at the end of a map (map may not be built) 16 | export const pushMap = options => { 17 | let array = getMap( options ); 18 | 19 | if( array == null ){ // if empty, put initial array 20 | setMap( extend( {}, options, { 21 | value: [ options.value ] 22 | } ) ); 23 | } else { 24 | array.push( options.value ); 25 | } 26 | }; 27 | 28 | // sets the value in a map (map may not be built) 29 | export const setMap = options => { 30 | let obj = options.map; 31 | let keys = options.keys; 32 | let l = keys.length; 33 | 34 | for( let i = 0; i < l; i++ ){ 35 | let key = keys[ i ]; 36 | 37 | if( is.plainObject( key ) ){ 38 | throw Error( 'Tried to set map with object key' ); 39 | } 40 | 41 | if( i < keys.length - 1 ){ 42 | 43 | // extend the map if necessary 44 | if( obj[ key ] == null ){ 45 | obj[ key ] = {}; 46 | } 47 | 48 | obj = obj[ key ]; 49 | } else { 50 | // set the value 51 | obj[ key ] = options.value; 52 | } 53 | } 54 | }; 55 | 56 | // gets the value in a map even if it's not built in places 57 | export const getMap = options => { 58 | let obj = options.map; 59 | let keys = options.keys; 60 | let l = keys.length; 61 | 62 | for( let i = 0; i < l; i++ ){ 63 | let key = keys[ i ]; 64 | 65 | if( is.plainObject( key ) ){ 66 | throw Error( 'Tried to get map with object key' ); 67 | } 68 | 69 | obj = obj[ key ]; 70 | 71 | if( obj == null ){ 72 | return obj; 73 | } 74 | } 75 | 76 | return obj; 77 | }; 78 | 79 | // deletes the entry in the map 80 | export const deleteMap = options => { 81 | let obj = options.map; 82 | let keys = options.keys; 83 | let l = keys.length; 84 | let keepChildren = options.keepChildren; 85 | 86 | for( let i = 0; i < l; i++ ){ 87 | let key = keys[ i ]; 88 | 89 | if( is.plainObject( key ) ){ 90 | throw Error( 'Tried to delete map with object key' ); 91 | } 92 | 93 | let lastKey = i === options.keys.length - 1; 94 | if( lastKey ){ 95 | 96 | if( keepChildren ){ // then only delete child fields not in keepChildren 97 | let children = Object.keys( obj ); 98 | 99 | for( let j = 0; j < children.length; j++ ){ 100 | let child = children[j]; 101 | 102 | if( !keepChildren[ child ] ){ 103 | obj[ child ] = undefined; 104 | } 105 | } 106 | } else { 107 | obj[ key ] = undefined; 108 | } 109 | 110 | } else { 111 | obj = obj[ key ]; 112 | } 113 | } 114 | }; 115 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/util/memoize.js: -------------------------------------------------------------------------------- 1 | export const memoize = ( fn, keyFn ) => { 2 | if( !keyFn ){ 3 | keyFn = function(){ 4 | if( arguments.length === 1 ){ 5 | return arguments[0]; 6 | } else if( arguments.length === 0 ){ 7 | return 'undefined'; 8 | } 9 | 10 | let args = []; 11 | 12 | for( let i = 0; i < arguments.length; i++ ){ 13 | args.push( arguments[ i ] ); 14 | } 15 | 16 | return args.join( '$' ); 17 | }; 18 | } 19 | 20 | let memoizedFn = function(){ 21 | let self = this; 22 | let args = arguments; 23 | let ret; 24 | let k = keyFn.apply( self, args ); 25 | let cache = memoizedFn.cache; 26 | 27 | if( !(ret = cache[ k ]) ){ 28 | ret = cache[ k ] = fn.apply( self, args ); 29 | } 30 | 31 | return ret; 32 | }; 33 | 34 | memoizedFn.cache = {}; 35 | 36 | return memoizedFn; 37 | }; 38 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/util/regex.js: -------------------------------------------------------------------------------- 1 | export const number = '(?:[-+]?(?:(?:\\d+|\\d*\\.\\d+)(?:[Ee][+-]?\\d+)?))'; 2 | 3 | export const rgba = 'rgb[a]?\\((' + number + '[%]?)\\s*,\\s*(' + number + '[%]?)\\s*,\\s*(' + number + '[%]?)(?:\\s*,\\s*(' + number + '))?\\)'; 4 | export const rgbaNoBackRefs = 'rgb[a]?\\((?:' + number + '[%]?)\\s*,\\s*(?:' + number + '[%]?)\\s*,\\s*(?:' + number + '[%]?)(?:\\s*,\\s*(?:' + number + '))?\\)'; 5 | 6 | export const hsla = 'hsl[a]?\\((' + number + ')\\s*,\\s*(' + number + '[%])\\s*,\\s*(' + number + '[%])(?:\\s*,\\s*(' + number + '))?\\)'; 7 | export const hslaNoBackRefs = 'hsl[a]?\\((?:' + number + ')\\s*,\\s*(?:' + number + '[%])\\s*,\\s*(?:' + number + '[%])(?:\\s*,\\s*(?:' + number + '))?\\)'; 8 | 9 | export const hex3 = '\\#[0-9a-fA-F]{3}'; 10 | export const hex6 = '\\#[0-9a-fA-F]{6}'; 11 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/util/sort.js: -------------------------------------------------------------------------------- 1 | export const ascending = ( a, b ) => { 2 | if( a < b ){ 3 | return -1; 4 | } else if( a > b ){ 5 | return 1; 6 | } else { 7 | return 0; 8 | } 9 | }; 10 | 11 | export const descending = ( a, b ) => { 12 | return -1 * ascending( a, b ); 13 | }; 14 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/util/strings.js: -------------------------------------------------------------------------------- 1 | import * as is from '../is'; 2 | import { memoize } from './memoize'; 3 | 4 | export const camel2dash = memoize(str => { 5 | return str.replace( /([A-Z])/g, v => { 6 | return '-' + v.toLowerCase(); 7 | } ); 8 | }); 9 | 10 | export const dash2camel = memoize(str => { 11 | return str.replace( /(-\w)/g, v => { 12 | return v[1].toUpperCase(); 13 | } ); 14 | }); 15 | 16 | export const prependCamel = memoize(( prefix, str ) => { 17 | return prefix + str[0].toUpperCase() + str.substring(1); 18 | }, ( prefix, str ) => { 19 | return prefix + '$' + str; 20 | }); 21 | 22 | export const capitalize = str => { 23 | if( is.emptyString( str ) ){ 24 | return str; 25 | } 26 | 27 | return str.charAt( 0 ).toUpperCase() + str.substring( 1 ); 28 | }; 29 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/util/timing.js: -------------------------------------------------------------------------------- 1 | import window from '../window'; 2 | import debounce from 'lodash.debounce'; 3 | 4 | var performance = window ? window.performance : null; 5 | 6 | var pnow = performance && performance.now ? () => performance.now() : () => Date.now(); 7 | 8 | var raf = (function(){ 9 | if( window ) { 10 | if( window.requestAnimationFrame ){ 11 | return function( fn ){ window.requestAnimationFrame( fn ); }; 12 | } else if( window.mozRequestAnimationFrame ){ 13 | return function( fn ){ window.mozRequestAnimationFrame( fn ); }; 14 | } else if( window.webkitRequestAnimationFrame ){ 15 | return function( fn ){ window.webkitRequestAnimationFrame( fn ); }; 16 | } else if( window.msRequestAnimationFrame ){ 17 | return function( fn ){ window.msRequestAnimationFrame( fn ); }; 18 | } 19 | } 20 | 21 | return function( fn ){ 22 | if( fn ){ 23 | setTimeout( function(){ 24 | fn( pnow() ); 25 | }, 1000 / 60 ); 26 | } 27 | }; 28 | })(); 29 | 30 | export const requestAnimationFrame = fn => raf( fn ); 31 | 32 | export const performanceNow = pnow; 33 | 34 | export const now = () => Date.now(); 35 | 36 | export { debounce }; 37 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/version.js: -------------------------------------------------------------------------------- 1 | export default process.env.VERSION; 2 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/cytoscape/src/window.js: -------------------------------------------------------------------------------- 1 | export default ( typeof window === 'undefined' ? null : window ); // eslint-disable-line no-undef 2 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/graph.js: -------------------------------------------------------------------------------- 1 | let elementsData; 2 | // let elementsData = JSON.parse(`[{ 3 | // "data": {"id": "a"} 4 | // }, { 5 | // "data": {"id": "b"} 6 | // }, { 7 | // "data": {"id": "c"} 8 | // }, { 9 | // "data": {"id": "e0", "source": "a", "target": "b"} 10 | // }]`); 11 | 12 | let cy = window.cy = cytoscape({ 13 | container: document.getElementById('cy'), 14 | 15 | boxSelectionEnabled: true, 16 | autounselectify: false, 17 | idealEdgeLength: 200, 18 | 19 | layout: { 20 | name: 'cose' 21 | }, 22 | 23 | style: cytoscape.stylesheet() 24 | .selector('node') 25 | .css({ 26 | 'height': 'mapData(weight, 0, 30, 20, 60)', 27 | 'width': 'mapData(weight, 0, 30, 20, 60)', 28 | 'color': '#707070', 29 | 'text-opacity': 1, 30 | 'text-valign': 'bottom', 31 | 'text-halign': 'center', 32 | 'font-size': '10px', 33 | }) 34 | .selector('node:unselected') 35 | .css({ 36 | 'background-color': '#969696', 37 | }) 38 | .selector('node:selected, node:grabbed') 39 | .css({ 40 | 'content': 'data(label)', 41 | 'background-color': '#8BA7BD', 42 | }) 43 | .selector('edge') 44 | .css({ 45 | 'curve-style': 'straight', 46 | 'width': 8, 47 | 'opacity': 0.5, 48 | 'line-color': '#383838' 49 | }), 50 | 51 | elements: elementsData 52 | }); -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Graph 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/note-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | id: 4 | name: 5 | date: 6 | tags: [ ] 7 | backlinks: [ ] 8 | 9 | --- 10 | 11 | # 12 | 13 | ## References 14 | 15 | ## Quotes 16 | 17 | ## Sources 18 | -------------------------------------------------------------------------------- /src/for_zettelkasten_dir/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Helvertica, Arial, sans-serif; 3 | font-size: 10px; 4 | background: #282828; 5 | } 6 | 7 | #cy { 8 | width: 100%; 9 | height: 100%; 10 | position: absolute; 11 | left: 0; 12 | top: 0; 13 | z-index: 999; 14 | } -------------------------------------------------------------------------------- /src/graph/graph_edge.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, Deserialize, Serialize)] 4 | pub struct GraphEdge { 5 | pub id: String, 6 | pub source: String, 7 | pub target: String, 8 | } 9 | 10 | impl GraphEdge { 11 | pub fn from(id: &str, source: &str, target: &str) -> Self { 12 | GraphEdge { 13 | id: id.to_string(), 14 | source: source.to_string(), 15 | target: target.to_string(), 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/graph/graph_node.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, Deserialize, Serialize)] 4 | pub struct GraphNode { 5 | pub id: String, 6 | pub label: String, 7 | pub weight: usize, 8 | } 9 | 10 | impl GraphNode { 11 | pub fn from(id: &str, label: &str, weight: usize) -> Self { 12 | GraphNode { 13 | id: id.to_string(), 14 | label: label.to_string(), 15 | weight, 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/graph/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod graph_edge; 2 | pub mod graph_node; 3 | pub mod main; 4 | -------------------------------------------------------------------------------- /src/history.rs: -------------------------------------------------------------------------------- 1 | use std::collections::VecDeque; 2 | use std::ffi::OsStr; 3 | use std::fs::File; 4 | use std::io::{Read, Write}; 5 | use std::path::PathBuf; 6 | 7 | pub struct History { 8 | pub note_history_capacity: usize, 9 | note_history: VecDeque, 10 | history_file_path: PathBuf, 11 | } 12 | 13 | impl History { 14 | pub fn new() -> History { 15 | return History { 16 | note_history: VecDeque::new(), 17 | note_history_capacity: 100, 18 | history_file_path: PathBuf::default(), 19 | }; 20 | } 21 | 22 | pub fn init(&mut self, file_path: &OsStr) -> Result<(), String> { 23 | self.history_file_path = PathBuf::from(file_path).join("history"); 24 | return self.load(); 25 | } 26 | 27 | pub fn add(&mut self, note_id: &str) -> Result<(), String> { 28 | if self.note_history.contains(¬e_id.to_string()) { 29 | self.note_history.retain(|x| x != ¬e_id.to_string()); 30 | } else { 31 | if self.note_history.len() >= self.note_history_capacity { 32 | self.note_history.pop_back(); 33 | } 34 | } 35 | 36 | self.note_history.push_front(note_id.to_string()); 37 | 38 | return self.save(); 39 | } 40 | 41 | fn save(&self) -> Result<(), String> { 42 | let mut history_file = match self.create_history_file() { 43 | Ok(value) => value, 44 | Err(error) => return Err(error), 45 | }; 46 | 47 | let mut is_first_entry = true; 48 | for note_id in self.note_history.iter() { 49 | let history_entry; 50 | if is_first_entry { 51 | history_entry = note_id.to_string(); 52 | is_first_entry = false; 53 | } else { 54 | history_entry = format!("\n{}", note_id); 55 | } 56 | 57 | if let Err(error) = history_file.write(&history_entry.as_bytes()) { 58 | return Err(format!( 59 | "save_note_history: couldn't write note id {} to history file: {}", 60 | note_id, error 61 | )); 62 | } 63 | } 64 | 65 | return Ok(()); 66 | } 67 | 68 | fn load(&mut self) -> Result<(), String> { 69 | let mut history_file = match File::open(&self.history_file_path) { 70 | Ok(value) => value, 71 | Err(_) => { 72 | return match self.create_history_file() { 73 | Ok(_) => Ok(()), 74 | Err(error) => Err(error), 75 | } 76 | } 77 | }; 78 | 79 | let mut note_history_string = String::new(); 80 | if let Err(error) = history_file.read_to_string(&mut note_history_string) { 81 | return Err(format!( 82 | "load_note_history: couldn't load note history: {}", 83 | error 84 | )); 85 | } 86 | 87 | self.note_history.clear(); 88 | for note_id in note_history_string.split('\n') { 89 | self.note_history.push_back(note_id.to_string()); 90 | } 91 | 92 | return Ok(()); 93 | } 94 | 95 | fn create_history_file(&self) -> Result { 96 | let history_file = match File::create(&self.history_file_path) { 97 | Ok(value) => value, 98 | Err(error) => { 99 | return Err(format!( 100 | "save_note_history: couldn't access history file at '{}': {}", 101 | self.history_file_path.to_string_lossy(), 102 | error 103 | )); 104 | } 105 | }; 106 | 107 | return Ok(history_file); 108 | } 109 | 110 | pub fn list(&self) -> Vec { 111 | return Vec::from(self.note_history.clone()); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/message.rs: -------------------------------------------------------------------------------- 1 | use colored::*; 2 | use indoc::indoc; 3 | 4 | pub struct Message; 5 | impl Message { 6 | pub fn display_correct_note_format() { 7 | Message::hint(indoc! {r##" 8 | the format of a note should look like this: 9 | 10 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11 | --- 12 | 13 | name: example-name 14 | date: yyyy-mm-dd HH:MM:SS 15 | tags: [ tag1, #tag2, tag-3 ] 16 | backlinks: [ ] 17 | 18 | --- 19 | 20 | custom note content in markdown (it doesn't matter what is written here) 21 | 22 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 23 | 24 | "##}); 25 | } 26 | 27 | pub fn error(message: &str) { 28 | println!("{} {}", "error:".bold().red(), message); 29 | } 30 | 31 | pub fn warning(message: &str) { 32 | println!("{} {}", "warning:".bold().yellow(), message); 33 | } 34 | 35 | pub fn hint(message: &str) { 36 | println!("{} {}", "hint:".bold().yellow(), message); 37 | } 38 | 39 | pub fn info(message: &str) { 40 | println!("{} {}", "info:".bold().blue(), message); 41 | } 42 | 43 | pub fn example(message: &str) { 44 | println!("\n{}\n{}\n", "example:".bold().yellow(), message); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/note.rs: -------------------------------------------------------------------------------- 1 | use chrono::{DateTime, Local}; 2 | 3 | pub struct Note { 4 | pub note_id: String, 5 | pub note_name: String, 6 | pub file_name: String, 7 | pub creation_date_time: Option>, 8 | } 9 | 10 | impl Default for Note { 11 | fn default() -> Self { 12 | return Note { 13 | note_id: String::default(), 14 | note_name: String::default(), 15 | file_name: String::default(), 16 | creation_date_time: Some(Local::now()), 17 | }; 18 | } 19 | } 20 | 21 | impl Note { 22 | pub fn new( 23 | note_id: String, 24 | note_name: String, 25 | file_name: String, 26 | creation_date_time: DateTime, 27 | ) -> Self { 28 | return Note { 29 | note_id, 30 | note_name, 31 | file_name, 32 | creation_date_time: Some(creation_date_time), 33 | }; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/note_link.rs: -------------------------------------------------------------------------------- 1 | pub struct NoteLink { 2 | pub source_note_id: String, 3 | pub target_note_id: String, 4 | } 5 | 6 | impl NoteLink { 7 | pub fn new(source_note_id: String, target_note_id: String) -> Self { 8 | NoteLink { 9 | source_note_id, 10 | target_note_id, 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/note_property.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | 3 | #[derive(Debug)] 4 | pub enum NoteProperty { 5 | NoteId, 6 | NoteName, 7 | CreationDate, 8 | // FileName, 9 | } 10 | 11 | impl NoteProperty { 12 | pub fn to_db_string(&self) -> String { 13 | match self { 14 | NoteProperty::NoteId => "note_id".to_string(), 15 | NoteProperty::NoteName => "note_name".to_string(), 16 | NoteProperty::CreationDate => "creation_date".to_string(), 17 | // NoteProperty::FileName => "file_name".to_string(), 18 | } 19 | } 20 | 21 | pub fn to_metadata_identifier(&self) -> String { 22 | match self { 23 | NoteProperty::NoteId => "id".to_string(), 24 | NoteProperty::NoteName => "name".to_string(), 25 | NoteProperty::CreationDate => "date".to_string(), 26 | // NoteProperty::FileName => "".to_string(), 27 | } 28 | } 29 | } 30 | 31 | impl fmt::Display for NoteProperty { 32 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 33 | write!(f, "{:?}", self) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/note_tagging.rs: -------------------------------------------------------------------------------- 1 | use std::hash::{Hash, Hasher}; 2 | 3 | #[derive(Clone)] 4 | pub struct NoteTagging { 5 | pub note_id: String, 6 | pub tag_name: Option, 7 | } 8 | 9 | impl NoteTagging { 10 | pub fn from(note_id: String, tag_name: Option) -> Self { 11 | NoteTagging { 12 | note_id: note_id, 13 | tag_name: tag_name, 14 | } 15 | } 16 | } 17 | 18 | impl PartialEq for NoteTagging { 19 | fn eq(&self, other: &Self) -> bool { 20 | self.note_id == other.note_id 21 | } 22 | } 23 | 24 | impl Eq for NoteTagging {} 25 | 26 | impl Hash for NoteTagging { 27 | fn hash(&self, state: &mut H) { 28 | self.note_id.hash(state); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/note_type.rs: -------------------------------------------------------------------------------- 1 | pub enum NoteType { 2 | Topic, 3 | Quote, 4 | Journal, 5 | } 6 | -------------------------------------------------------------------------------- /src/settings.rs: -------------------------------------------------------------------------------- 1 | use crate::history::History; 2 | use crate::message::Message; 3 | 4 | use std::ffi::OsString; 5 | 6 | pub struct Settings { 7 | pub notes_dir: OsString, 8 | pub zettelkasten_dir: OsString, 9 | pub backlinking_enabled: bool, 10 | pub print_to_stdout: bool, 11 | pub show_interactive_dialogs: bool, 12 | pub note_history: History, 13 | } 14 | 15 | impl Settings { 16 | pub fn init(notes_dir: OsString, zettelkasten_dir: OsString) -> Self { 17 | let mut settings = Settings { 18 | notes_dir: notes_dir, 19 | zettelkasten_dir: zettelkasten_dir, 20 | note_history: History::new(), 21 | backlinking_enabled: true, 22 | print_to_stdout: true, 23 | show_interactive_dialogs: true, 24 | }; 25 | 26 | if let Err(error) = settings 27 | .note_history 28 | .init(&settings.zettelkasten_dir.as_os_str()) 29 | { 30 | Message::info(&("initializing history: ".to_string() + &error)); 31 | } 32 | return settings; 33 | } 34 | } 35 | --------------------------------------------------------------------------------