├── AUTHORS ├── COPYING ├── CREDITS ├── README.md ├── Safari ├── OSDS (macOS)Release.entitlements ├── OSDS.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── Shared (App) │ ├── Assets.xcassets │ │ ├── AccentColor.colorset │ │ │ └── Contents.json │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── ios-marketing-icon-1024@1x.png │ │ │ ├── ipad-icon-20@1x.png │ │ │ ├── ipad-icon-20@2x.png │ │ │ ├── ipad-icon-29@1x.png │ │ │ ├── ipad-icon-29@2x.png │ │ │ ├── ipad-icon-40@1x.png │ │ │ ├── ipad-icon-40@2x.png │ │ │ ├── ipad-icon-76@1x.png │ │ │ ├── ipad-icon-76@2x.png │ │ │ ├── ipad-icon-83.5@2x.png │ │ │ ├── iphone-icon-20@2x.png │ │ │ ├── iphone-icon-20@3x.png │ │ │ ├── iphone-icon-29@2x.png │ │ │ ├── iphone-icon-29@3x.png │ │ │ ├── iphone-icon-40@2x.png │ │ │ ├── iphone-icon-40@3x.png │ │ │ ├── iphone-icon-60@2x.png │ │ │ ├── iphone-icon-60@3x.png │ │ │ ├── mac-icon-128@1x.png │ │ │ ├── mac-icon-128@2x.png │ │ │ ├── mac-icon-16@1x.png │ │ │ ├── mac-icon-16@2x.png │ │ │ ├── mac-icon-256@1x.png │ │ │ ├── mac-icon-256@2x.png │ │ │ ├── mac-icon-32@1x.png │ │ │ ├── mac-icon-32@2x.png │ │ │ ├── mac-icon-512@1x.png │ │ │ └── mac-icon-512@2x.png │ │ ├── Contents.json │ │ └── LargeIcon.imageset │ │ │ ├── Contents.json │ │ │ └── icon128.png │ ├── Base.lproj │ │ └── Main.html │ ├── Resources │ │ ├── Icon.png │ │ ├── Script.js │ │ └── Style.css │ └── ViewController.swift ├── Shared (Extension) │ ├── Resources │ │ └── .gitkeep │ └── SafariWebExtensionHandler.swift ├── iOS (App) │ ├── AppDelegate.swift │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ └── SceneDelegate.swift ├── iOS (Extension) │ └── Info.plist ├── macOS (App) │ ├── AppDelegate.swift │ ├── Base.lproj │ │ └── Main.storyboard │ ├── Info.plist │ └── OSDS.entitlements └── macOS (Extension) │ ├── Info.plist │ └── OSDS.entitlements ├── prepare_chrome.sh ├── prepare_ff.sh ├── prepare_safari.sh └── src ├── OidcWebid.js ├── background.html ├── background.js ├── background_web.js ├── browser.js ├── browser_ff.js ├── browser_sf.js ├── chat-inject.js ├── chat-srv.js ├── content.css ├── converters.js ├── datablock.js ├── dataview.css ├── frame_scan.js ├── frame_text.js ├── handlers.js ├── helpers.js ├── helpers_ui.js ├── html_gen.js ├── images ├── chat.png ├── copy-icon.svg ├── icon128.png ├── icon16.png ├── icon48.png ├── message.svg ├── osds-icon-annotate-24.png ├── osds-icon-describe-24.png ├── osds-icon-download-24.png ├── osds-icon-query-24.png ├── osds-icon-rest-24.png ├── osds-icon-settings-24.png ├── osds-icon-upload-24.png ├── person-icon.svg ├── plus.svg ├── robot.svg ├── slink24.png ├── slogin24.png ├── throbber.gif ├── thumb-down.png ├── thumb-up.png └── uid.png ├── lib ├── FileSaver.js ├── RDFa.js ├── codemirror.js ├── css │ ├── codemirror.css │ ├── footable-0.1.css │ ├── github-markdown.css │ ├── img │ │ ├── down.png │ │ ├── minus.png │ │ ├── plus.png │ │ ├── sorting_sprite.png │ │ ├── trash.png │ │ └── up.png │ ├── smoothness │ │ ├── images │ │ │ ├── ui-bg_glass_55_fbf9ee_1x400.png │ │ │ ├── ui-bg_glass_65_ffffff_1x400.png │ │ │ ├── ui-bg_glass_75_dadada_1x400.png │ │ │ ├── ui-bg_glass_75_e6e6e6_1x400.png │ │ │ ├── ui-bg_glass_95_fef1ec_1x400.png │ │ │ ├── ui-bg_highlight-soft_75_cccccc_1x100.png │ │ │ ├── ui-icons_222222_256x240.png │ │ │ ├── ui-icons_2e83ff_256x240.png │ │ │ ├── ui-icons_454545_256x240.png │ │ │ ├── ui-icons_888888_256x240.png │ │ │ └── ui-icons_cd0a0a_256x240.png │ │ ├── jquery-ui.min.css │ │ └── theme.css │ └── yasqe.css ├── gpt3-encoder.js ├── highlight │ ├── default.min.css │ └── highlight.js ├── jquery-3.1.0.min.js ├── jquery-migrate-3.0.0.min.js ├── jquery-ui.min.js ├── jquery.mark.js ├── jsonld.js ├── markdown-it.js ├── md_view.html ├── microdatajs │ ├── jquery.microdata.js │ └── jquery.microdata.json.js ├── n3-browser.js ├── namespace.js ├── original │ ├── FileSaver.js │ ├── RDFa.js │ ├── jquery.microdata.json.js │ ├── jsonld.js │ ├── n3-browser.js │ └── yasqe.js ├── papaparse.js ├── posh.js ├── purify.js ├── rdflib.js ├── rss-parser.js ├── solid-client-authn.bundle.js ├── solid-client-authn.bundle.js.map ├── tidy.js └── yasqe.js ├── manifest.json ├── manifest.json.ff ├── manifest.json.sf ├── oidc-webid-inject.js ├── options.html ├── options.js ├── page_panel.html ├── page_panel.js ├── panel.html ├── panel.js ├── service_worker.js ├── service_worker_ff.js ├── service_worker_sf.js ├── settings.js ├── sniffer.js ├── sniffer_nano.js ├── social_sniffer.js ├── super_links.js ├── tabs.css ├── ttl_gen.js └── utils.js /AUTHORS: -------------------------------------------------------------------------------- 1 | # 2 | # List of Authors/Contributors 3 | # 4 | # This file is part of the OpenLink Structured Data Sniffer 5 | # 6 | # Copyright (C) 2015-2021 OpenLink Software 7 | # 8 | # This project is free software; you can redistribute it and/or modify it 9 | # under the terms of the GNU General Public License as published by the 10 | # Free Software Foundation; only version 2 of the License, dated June 1991. 11 | # 12 | # This program is distributed in the hope that it will be useful, but 13 | # WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | # General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License along 18 | # with this program; if not, write to the Free Software Foundation, Inc., 19 | # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | # 21 | # 22 | 23 | Current Maintainer 24 | ------------------ 25 | Patrick van Kleef opensource{at}openlinksw.com 26 | 27 | 28 | Author 29 | ------- 30 | Sergey Malinin smalinin{at}openlinksw.com 31 | 32 | 33 | Contributors 34 | ------------ 35 | 36 | This list may not complete. If you have contributed to this project and want to appear on this list, 37 | please email the current maintainer. 38 | -------------------------------------------------------------------------------- /CREDITS: -------------------------------------------------------------------------------- 1 | # 2 | # CREDITS 3 | # 4 | # This file is part of the OpenLink Structured Data Sniffer 5 | # 6 | # Copyright (C) 2015-2021 OpenLink Software 7 | # 8 | # This project is free software; you can redistribute it and/or modify it 9 | # under the terms of the GNU General Public License as published by the 10 | # Free Software Foundation; only version 2 of the License, dated June 1991. 11 | # 12 | # This program is distributed in the hope that it will be useful, but 13 | # WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | # General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License along 18 | # with this program; if not, write to the Free Software Foundation, Inc., 19 | # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | # 21 | # 22 | 23 | The OpenLink Software ODE Sniffer project wishes to acknowledge incorporation of code from the 24 | following projects: 25 | 26 | * jQuery 27 | Project : https://jquery.com/ 28 | License : https://github.com/jquery/jquery/blob/master/LICENSE.txt, looks like MIT license 29 | Description : jQuery is a fast, small, and feature-rich JavaScript library. It makes things 30 | like HTML document traversal and manipulation, event handling, animation, and Ajax 31 | much simpler with an easy-to-use API that works across a multitude of browsers. 32 | 33 | 34 | * jQuery migrate 35 | Project : https://github.com/jquery/jquery-migrate 36 | License : https://github.com/jquery/jquery-migrate/blob/master/LICENSE.txt, looks like MIT license 37 | Description : https://jqueryui.com/Migrate older jQuery code to jQuery 1.9+ 38 | 39 | * jQuery mark 40 | Project : https://github.com/julmot/mark.js/ 41 | License : The MIT License (MIT) 42 | Description : JavaScript keyword highlighting. Mark text with with options that fit every application. 43 | 44 | * jQuery UI 45 | Project : https://jqueryui.com/ 46 | License : https://github.com/jquery/jquery-ui/blob/master/LICENSE.txt 47 | Description : jQuery user interface library 48 | 49 | 50 | * jsonld.js 51 | Project : https://github.com/digitalbazaar/jsonld.js 52 | License : New BSD License (3-clause) 53 | Description : A JSON-LD Processor and API implementation in JavaScript. 54 | NOTE : This file was slightly adapted by OpenLink to comment out some unused code. 55 | The original file can be found in lib/original/jsonld.js for comparison. 56 | 57 | 58 | * Microdatajs 59 | Project : https://github.com/foolip/microdatajs 60 | License : MIT license 61 | Description : MicrodataJS is a jQuery plugin that provides an API for accessing Microdata 62 | inspired by (but by necessity slightly different from) the native DOM API. 63 | 64 | 65 | * N3.js 66 | Project : https://github.com/RubenVerborgh/N3.js 67 | License : MIT license 68 | Description : Lightning fast, asynchronous, streaming RDF for JavaScript. 69 | 70 | 71 | * RDFa.js 72 | Project : https://github.com/alexmilowski/green-turtle 73 | License : MIT license 74 | Description : An RDFa 1.1. implementation for browsers. 75 | NOTE : This file was slightly adapted by OpenLink to add some extra functionality and to 76 | comment out some unused code. The original file can be found in 77 | lib/original/RDFa.js for comparison. 78 | 79 | * rdflib.js 80 | Project : https://github.com/linkeddata/rdflib.js 81 | License : MIT license 82 | Description : Linked Data API for JavaScript 83 | 84 | 85 | * FileSaver.js 86 | Project : https://github.com/eligrey/FileSaver.js 87 | License : MIT license 88 | Description : A saveAs() FileSaver implementation. 89 | 90 | * CodeMirror 91 | Project : https://github.com/codemirror/CodeMirror 92 | License : MIT license 93 | Description : In-browser code editor http://codemirror.net/ 94 | 95 | * Yasqe 96 | Project : http://yasqe.yasgui.org/ 97 | License : MIT license 98 | Description : Yet Another Sparql Query Editor. 99 | 100 | * DOMPurify 101 | Project : https://github.com/cure53/DOMPurify 102 | License : Apache/Mozilla license 103 | Description : DOMPurify - a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, 104 | MathML and SVG. DOMPurify works with a secure default, but offers a lot 105 | of configurability and hooks. 106 | 107 | * markdown-it 108 | Project : https://github.com/markdown-it/markdown-it 109 | License : MIT license 110 | Description : Markdown parser, done right. 100% CommonMark support, extensions, syntax plugins & high speed 111 | 112 | * Highlight.js 113 | Project : https://github.com/highlightjs/highlight.js 114 | License : BSD-3-Clause license 115 | Description : JavaScript syntax highlighter with language auto-detection and zero dependencies. 116 | 117 | 118 | 119 | This list may not complete. If you feel any third party project is missing from this list, please 120 | email the current maintainer. 121 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenLink Structured Data Sniffer 2 | 3 | ## Intro 4 | The OpenLink Structured Data Sniffer (OSDS) is an extension for 5 | [Google Chrome](http://www.google.com/chrome/browser/), 6 | [Mozilla Firefox](http://www.mozilla.org/firefox/), 7 | [Apple Safari](http://www.apple.com/safari/), 8 | [Microsoft Edge](https://www.microsoft.com/microsoft-edge), 9 | [Opera](http://www.opera.com/) 10 | and other Chromium-based browsers, 11 | that detects, presents, and offers interaction interfaces for 12 | structured data (such as Knowledge Graphs) embedded in 13 | web pages using any of the following formats: 14 | 15 | - **CSV** 16 | - **JSON** 17 | - **JSON-LD** 18 | - **Microdata** 19 | - **Plain Old Semantic HTML (POSH)** 20 | - **RDFa** 21 | - **RDF-Turtle** 22 | - **RDF-XML** 23 | - **JSON** 24 | - **CSV** 25 | - **RSS** 26 | - **Atom** 27 | - **Markdown Tables** 28 | 29 | ## License 30 | Copyright 2015-2022 [OpenLink Software](mailto:opensource@openlinksw.com) 31 | 32 | This software is licensed under the GNU General Public License (see 33 | [COPYING](https://github.com/OpenLinkSoftware/OSDS_extension/blob/develop/COPYING)). 34 | 35 | **Note**: that the only valid version of the GPL license as far as this project is concerned is the 36 | original GNU General Public License Version 2, dated June 1991. 37 | 38 | ## Deployment 39 | To deploy this extension on your local machine you can either *clone the git source tree* or 40 | *download a source archive* and then *install the extension* into your Chrome or Opera browser on 41 | the same system. In most cases, you can also download a prebuilt extension binary from the store 42 | for your browser (Chromium-based browsers use the extension from the Chrome store; Safari uses 43 | the extension from the Apple App Store; Firefox uses the extension from the Firefox store; and 44 | Microsoft Edge uses the extension from the Microsoft store.) 45 | 46 | ### Clone the git source tree 47 | Clone the sources from github using the following commands, which will automatically download the latest develop branch: 48 | ```shell 49 | $ cd src 50 | $ git clone https://github.com/OpenLinkSoftware/OSDS_extension 51 | ``` 52 | 53 | ### Download a source archive 54 | Download and extract a `.tar.gz` or `.zip`, either from one of the 55 | [stable releases](https://github.com/OpenLinkSoftware/OSDS_extension/tags), 56 | or directly from one of the following links: 57 | 58 | - [latest stable `.tar.gz`](https://github.com/OpenLinkSoftware/OSDS_extension/archive/master.tar.gz) 59 | - [latest stable `.zip`](https://github.com/OpenLinkSoftware/OSDS_extension/archive/master.zip) 60 | - [latest development `.tar.gz`](https://github.com/OpenLinkSoftware/OSDS_extension/archive/develop.tar.gz) 61 | - [latest development `.zip`](https://github.com/OpenLinkSoftware/OSDS_extension/archive/develop.zip) 62 | 63 | 64 | ### Install the extension in Chrome 65 | To install this extension manually, take the following steps: 66 | 67 | 1. Open the Chrome browser 68 | 1. Select from menu: **Chrome** -> **Preferences** -> **Extensions** 69 | 1. Check the [X] **Developer mode** box 70 | 1. Choose the option **Load unpacked extension...** 71 | 1. Navigate to the folder containing the extracted source code 72 | 1. Press the **Select** button 73 | 74 | ### Install the extension in Microsoft Edge 75 | To install this extension manually, take the following steps: 76 | 77 | 1. Open the Edge browser 78 | 1. Select from menu: **Edge** -> **Preferences** -> **Extensions** 79 | 1. Check the [X] **Developer mode** box 80 | 1. Choose the option **Load unpacked extension...** 81 | 1. Navigate to the folder containing the extracted source code 82 | 1. Press the **Select** button 83 | 84 | ### Install the extension in Opera 85 | To install this extension manually use the following steps: 86 | 87 | 1. Open the Opera browser 88 | 1. In address bar type in **opera:extensions** 89 | 1. Press the **Developer Mode** button 90 | 1. Choose the option **Load unpacked extension...** 91 | 1. Navigate to the folder containing the extracted source 92 | 1. Press the **Select** button 93 | 94 | ### Install the extension in Firefox 95 | Download the [Firefox OSDS .zip](https://github.com/OpenLinkSoftware/OSDS_extension/releases/download/v2.16.1/OSDS_FF.zip) 96 | file and extract the .xpi file. 97 | 98 | NOTE: Only temporary install is possible for unsigned .xpi file in last versions of Firefox. 99 | 100 | To install this extension manually in Firefox, use the following steps: 101 | 102 | 1. Open the **Firefox** browser 103 | 1. In address bar type: **about:addons** or choose menu ** Add-ons** 104 | 1. Click on Gear icon and choose **Debug Add-ons** 105 | 1. Click on **Load Temporary Add-on** 106 | 1. Navigate to the directory where you extracted the OSDS_FF.xpi file, select this file and press the **Open** button 107 | 108 | 109 | ### Examples 110 | Navigate to a page containing structured data such as any of those below, and click on the sniffer icon that appears in the address bar: 111 | 112 | - [OpenLink Software Homepage](http://www.openlinksw.com/) 113 | - [BBC News Homepage](http://www.bbc.com/news) 114 | - [Ted.com talk by Susan Etlinger](https://www.ted.com/talks/susan_etlinger_what_do_we_do_with_all_this_big_data) 115 | - [DBpedia article on Semantic Web](http://dbpedia.org/page/Semantic_Web) 116 | 117 | -------------------------------------------------------------------------------- /Safari/OSDS (macOS)Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.network.client 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Safari/OSDS.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Safari/OSDS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "iphone-icon-20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "iphone-icon-20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "iphone-icon-29@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "iphone-icon-29@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "iphone-icon-40@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "iphone-icon-40@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "iphone-icon-60@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "iphone-icon-60@3x.png", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "size" : "20x20", 53 | "idiom" : "ipad", 54 | "filename" : "ipad-icon-20@1x.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "ipad-icon-20@2x.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "29x29", 65 | "idiom" : "ipad", 66 | "filename" : "ipad-icon-29@1x.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "ipad-icon-29@2x.png", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "size" : "40x40", 77 | "idiom" : "ipad", 78 | "filename" : "ipad-icon-40@1x.png", 79 | "scale" : "1x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "ipad-icon-40@2x.png", 85 | "scale" : "2x" 86 | }, 87 | { 88 | "size" : "76x76", 89 | "idiom" : "ipad", 90 | "filename" : "ipad-icon-76@1x.png", 91 | "scale" : "1x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "ipad-icon-76@2x.png", 97 | "scale" : "2x" 98 | }, 99 | { 100 | "size" : "83.5x83.5", 101 | "idiom" : "ipad", 102 | "filename" : "ipad-icon-83.5@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "1024x1024", 107 | "idiom" : "ios-marketing", 108 | "filename" : "ios-marketing-icon-1024@1x.png", 109 | "scale" : "1x" 110 | }, 111 | { 112 | "size" : "16x16", 113 | "idiom" : "mac", 114 | "filename" : "mac-icon-16@1x.png", 115 | "scale" : "1x" 116 | }, 117 | { 118 | "size" : "16x16", 119 | "idiom" : "mac", 120 | "filename" : "mac-icon-16@2x.png", 121 | "scale" : "2x" 122 | }, 123 | { 124 | "size" : "32x32", 125 | "idiom" : "mac", 126 | "filename" : "mac-icon-32@1x.png", 127 | "scale" : "1x" 128 | }, 129 | { 130 | "size" : "32x32", 131 | "idiom" : "mac", 132 | "filename" : "mac-icon-32@2x.png", 133 | "scale" : "2x" 134 | }, 135 | { 136 | "size" : "128x128", 137 | "idiom" : "mac", 138 | "filename" : "mac-icon-128@1x.png", 139 | "scale" : "1x" 140 | }, 141 | { 142 | "size" : "128x128", 143 | "idiom" : "mac", 144 | "filename" : "mac-icon-128@2x.png", 145 | "scale" : "2x" 146 | }, 147 | { 148 | "size" : "256x256", 149 | "idiom" : "mac", 150 | "filename" : "mac-icon-256@1x.png", 151 | "scale" : "1x" 152 | }, 153 | { 154 | "size" : "256x256", 155 | "idiom" : "mac", 156 | "filename" : "mac-icon-256@2x.png", 157 | "scale" : "2x" 158 | }, 159 | { 160 | "size" : "512x512", 161 | "idiom" : "mac", 162 | "filename" : "mac-icon-512@1x.png", 163 | "scale" : "1x" 164 | }, 165 | { 166 | "size" : "512x512", 167 | "idiom" : "mac", 168 | "filename" : "mac-icon-512@2x.png", 169 | "scale" : "2x" 170 | } 171 | ], 172 | "info" : { 173 | "version" : 1, 174 | "author" : "xcode" 175 | } 176 | } -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/ios-marketing-icon-1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/ios-marketing-icon-1024@1x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/ipad-icon-20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/ipad-icon-20@1x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/ipad-icon-20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/ipad-icon-20@2x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/ipad-icon-29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/ipad-icon-29@1x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/ipad-icon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/ipad-icon-29@2x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/ipad-icon-40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/ipad-icon-40@1x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/ipad-icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/ipad-icon-40@2x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/ipad-icon-76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/ipad-icon-76@1x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/ipad-icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/ipad-icon-76@2x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/ipad-icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/ipad-icon-83.5@2x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/iphone-icon-20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/iphone-icon-20@2x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/iphone-icon-20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/iphone-icon-20@3x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/iphone-icon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/iphone-icon-29@2x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/iphone-icon-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/iphone-icon-29@3x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/iphone-icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/iphone-icon-40@2x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/iphone-icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/iphone-icon-40@3x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/iphone-icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/iphone-icon-60@2x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/iphone-icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/iphone-icon-60@3x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-128@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-128@1x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-128@2x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-16@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-16@1x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-16@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-16@2x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-256@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-256@1x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-256@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-256@2x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-32@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-32@1x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-32@2x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-512@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-512@1x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/AppIcon.appiconset/mac-icon-512@2x.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/LargeIcon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "icon128.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Safari/Shared (App)/Assets.xcassets/LargeIcon.imageset/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Assets.xcassets/LargeIcon.imageset/icon128.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Base.lproj/Main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | OpenLink Structured Data Sniffer Icon 14 |

You can turn on OpenLink Structured Data Sniffer’s Safari extension in Settings.

15 |

You can turn on OpenLink Structured Data Sniffer’s extension in Safari Extensions preferences.

16 |

OpenLink Structured Data Sniffer’s extension is currently on. You can turn it off in Safari Extensions preferences.

17 |

OpenLink Structured Data Sniffer’s extension is currently off. You can turn it on in Safari Extensions preferences.

18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Safari/Shared (App)/Resources/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (App)/Resources/Icon.png -------------------------------------------------------------------------------- /Safari/Shared (App)/Resources/Script.js: -------------------------------------------------------------------------------- 1 | function show(platform, enabled) { 2 | document.body.classList.add(`platform-${platform}`); 3 | 4 | if (typeof enabled === "boolean") { 5 | document.body.classList.toggle(`state-on`, enabled); 6 | document.body.classList.toggle(`state-off`, !enabled); 7 | } else { 8 | document.body.classList.remove(`state-on`); 9 | document.body.classList.remove(`state-off`); 10 | } 11 | } 12 | 13 | function openPreferences() { 14 | webkit.messageHandlers.controller.postMessage("open-preferences"); 15 | } 16 | 17 | document.querySelector("button.open-preferences").addEventListener("click", openPreferences); 18 | -------------------------------------------------------------------------------- /Safari/Shared (App)/Resources/Style.css: -------------------------------------------------------------------------------- 1 | * { 2 | -webkit-user-select: none; 3 | -webkit-user-drag: none; 4 | cursor: default; 5 | } 6 | 7 | :root { 8 | color-scheme: light dark; 9 | 10 | --spacing: 20px; 11 | } 12 | 13 | html { 14 | height: 100%; 15 | } 16 | 17 | body { 18 | display: flex; 19 | align-items: center; 20 | justify-content: center; 21 | flex-direction: column; 22 | 23 | gap: var(--spacing); 24 | margin: 0 calc(var(--spacing) * 2); 25 | height: 100%; 26 | 27 | font: -apple-system-short-body; 28 | text-align: center; 29 | } 30 | 31 | body:not(.platform-mac, .platform-ios) :is(.platform-mac, .platform-ios) { 32 | display: none; 33 | } 34 | 35 | body.platform-ios .platform-mac { 36 | display: none; 37 | } 38 | 39 | body.platform-mac .platform-ios { 40 | display: none; 41 | } 42 | 43 | body.platform-ios .platform-mac { 44 | display: none; 45 | } 46 | 47 | body:not(.state-on, .state-off) :is(.state-on, .state-off) { 48 | display: none; 49 | } 50 | 51 | body.state-on :is(.state-off, .state-unknown) { 52 | display: none; 53 | } 54 | 55 | body.state-off :is(.state-on, .state-unknown) { 56 | display: none; 57 | } 58 | 59 | button { 60 | font-size: 1em; 61 | } 62 | -------------------------------------------------------------------------------- /Safari/Shared (App)/ViewController.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenLink Structured Data Sniffer 3 | * 4 | * Copyright (C) 2015-2021 OpenLink Software 5 | * 6 | * This project is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License as published by the 8 | * Free Software Foundation; only version 2 of the License, dated June 1991. 9 | * 10 | * This program is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, write to the Free Software Foundation, Inc., 17 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | import WebKit 22 | 23 | #if os(iOS) 24 | import UIKit 25 | typealias PlatformViewController = UIViewController 26 | #elseif os(macOS) 27 | import Cocoa 28 | import SafariServices 29 | typealias PlatformViewController = NSViewController 30 | #endif 31 | 32 | let extensionBundleIdentifier = "com.openlinksw.OSDS.Extension" 33 | 34 | class ViewController: PlatformViewController, WKNavigationDelegate, WKScriptMessageHandler { 35 | 36 | @IBOutlet var webView: WKWebView! 37 | 38 | override func viewDidLoad() { 39 | super.viewDidLoad() 40 | 41 | self.webView.navigationDelegate = self 42 | 43 | #if os(iOS) 44 | self.webView.scrollView.isScrollEnabled = false 45 | #endif 46 | 47 | self.webView.configuration.userContentController.add(self, name: "controller") 48 | 49 | self.webView.loadFileURL(Bundle.main.url(forResource: "Main", withExtension: "html")!, allowingReadAccessTo: Bundle.main.resourceURL!) 50 | } 51 | 52 | func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { 53 | #if os(iOS) 54 | webView.evaluateJavaScript("show('ios')") 55 | #elseif os(macOS) 56 | webView.evaluateJavaScript("show('mac')") 57 | 58 | SFSafariExtensionManager.getStateOfSafariExtension(withIdentifier: extensionBundleIdentifier) { (state, error) in 59 | guard let state = state, error == nil else { 60 | // Insert code to inform the user that something went wrong. 61 | return 62 | } 63 | 64 | DispatchQueue.main.async { 65 | webView.evaluateJavaScript("show('mac', \(state.isEnabled)") 66 | } 67 | } 68 | #endif 69 | } 70 | 71 | func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { 72 | #if os(macOS) 73 | if (message.body as! String != "open-preferences") { 74 | return; 75 | } 76 | 77 | SFSafariApplication.showPreferencesForExtension(withIdentifier: extensionBundleIdentifier) { error in 78 | guard error == nil else { 79 | // Insert code to inform the user that something went wrong. 80 | return 81 | } 82 | 83 | DispatchQueue.main.async { 84 | NSApplication.shared.terminate(nil) 85 | } 86 | } 87 | #endif 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /Safari/Shared (Extension)/Resources/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/Safari/Shared (Extension)/Resources/.gitkeep -------------------------------------------------------------------------------- /Safari/Shared (Extension)/SafariWebExtensionHandler.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenLink Structured Data Sniffer 3 | * 4 | * Copyright (C) 2015-2021 OpenLink Software 5 | * 6 | * This project is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License as published by the 8 | * Free Software Foundation; only version 2 of the License, dated June 1991. 9 | * 10 | * This program is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, write to the Free Software Foundation, Inc., 17 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | import SafariServices 22 | import os.log 23 | 24 | let SFExtensionMessageKey = "message" 25 | 26 | class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { 27 | 28 | func beginRequest(with context: NSExtensionContext) { 29 | let item = context.inputItems[0] as! NSExtensionItem 30 | let message = item.userInfo?[SFExtensionMessageKey] 31 | os_log(.default, "Received message from browser.runtime.sendNativeMessage: %@", message as! CVarArg) 32 | 33 | let response = NSExtensionItem() 34 | response.userInfo = [ SFExtensionMessageKey: [ "Response to": message ] ] 35 | 36 | context.completeRequest(returningItems: [response], completionHandler: nil) 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /Safari/iOS (App)/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenLink Structured Data Sniffer 3 | * 4 | * Copyright (C) 2015-2021 OpenLink Software 5 | * 6 | * This project is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License as published by the 8 | * Free Software Foundation; only version 2 of the License, dated June 1991. 9 | * 10 | * This program is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, write to the Free Software Foundation, Inc., 17 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | import UIKit 22 | 23 | @main 24 | class AppDelegate: UIResponder, UIApplicationDelegate { 25 | 26 | var window: UIWindow? 27 | 28 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 29 | // Override point for customization after application launch. 30 | return true 31 | } 32 | 33 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 34 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /Safari/iOS (App)/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /Safari/iOS (App)/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Safari/iOS (App)/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SFSafariWebExtensionConverterVersion 6 | 13.0 7 | UIApplicationSceneManifest 8 | 9 | UIApplicationSupportsMultipleScenes 10 | 11 | UISceneConfigurations 12 | 13 | UIWindowSceneSessionRoleApplication 14 | 15 | 16 | UISceneConfigurationName 17 | Default Configuration 18 | UISceneDelegateClassName 19 | $(PRODUCT_MODULE_NAME).SceneDelegate 20 | UISceneStoryboardFile 21 | Main 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Safari/iOS (App)/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenLink Structured Data Sniffer 3 | * 4 | * Copyright (C) 2015-2021 OpenLink Software 5 | * 6 | * This project is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License as published by the 8 | * Free Software Foundation; only version 2 of the License, dated June 1991. 9 | * 10 | * This program is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, write to the Free Software Foundation, Inc., 17 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | import UIKit 22 | 23 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 24 | 25 | var window: UIWindow? 26 | 27 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 28 | guard let _ = (scene as? UIWindowScene) else { return } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /Safari/iOS (Extension)/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSExtension 6 | 7 | NSExtensionPointIdentifier 8 | com.apple.Safari.web-extension 9 | NSExtensionPrincipalClass 10 | $(PRODUCT_MODULE_NAME).SafariWebExtensionHandler 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Safari/macOS (App)/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenLink Structured Data Sniffer 3 | * 4 | * Copyright (C) 2015-2021 OpenLink Software 5 | * 6 | * This project is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License as published by the 8 | * Free Software Foundation; only version 2 of the License, dated June 1991. 9 | * 10 | * This program is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, write to the Free Software Foundation, Inc., 17 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | import Cocoa 22 | 23 | @main 24 | class AppDelegate: NSObject, NSApplicationDelegate { 25 | 26 | func applicationDidFinishLaunching(_ notification: Notification) { 27 | // Override point for customization after application launch. 28 | } 29 | 30 | func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 31 | return true 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /Safari/macOS (App)/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /Safari/macOS (App)/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ITSAppUsesNonExemptEncryption 6 | 7 | SFSafariWebExtensionConverterVersion 8 | 13.0 9 | 10 | 11 | -------------------------------------------------------------------------------- /Safari/macOS (App)/OSDS.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.network.client 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Safari/macOS (Extension)/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSExtension 6 | 7 | NSExtensionPointIdentifier 8 | com.apple.Safari.web-extension 9 | NSExtensionPrincipalClass 10 | $(PRODUCT_MODULE_NAME).SafariWebExtensionHandler 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Safari/macOS (Extension)/OSDS.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /prepare_chrome.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | EXT_DIRNAME=./OSDS_Chrome 3 | EXT_SRC=./src 4 | 5 | rm -rf $EXT_DIRNAME 6 | 7 | mkdir -pv $EXT_DIRNAME 8 | 9 | 10 | SRC_DIR=./ 11 | DST_DIR=$EXT_DIRNAME 12 | 13 | #copy info files 14 | for I_DIR in AUTHORS COPYING CREDITS; do 15 | cp -va $SRC_DIR/$I_DIR $DST_DIR/ 16 | done 17 | 18 | 19 | SRC_DIR=$EXT_SRC 20 | DST_DIR=$EXT_DIRNAME 21 | 22 | #copy common files 23 | for I_DIR in background.js background_web.js chat-inject.js chat-srv.js content.css converters.js datablock.js; do 24 | cp -va $SRC_DIR/$I_DIR $DST_DIR/ 25 | done 26 | 27 | for I_DIR in dataview.css frame_scan.js frame_text.js handlers.js helpers.js helpers_ui.js html_gen.js ; do 28 | cp -va $SRC_DIR/$I_DIR $DST_DIR/ 29 | done 30 | 31 | for I_DIR in oidc-webid-inject.js OidcWebid.js options.html options.js page_panel.html page_panel.js ; do 32 | cp -va $SRC_DIR/$I_DIR $DST_DIR/ 33 | done 34 | 35 | for I_DIR in panel.html panel.js settings.js sniffer.js sniffer_nano.js social_sniffer.js super_links.js ; do 36 | cp -va $SRC_DIR/$I_DIR $DST_DIR/ 37 | done 38 | 39 | for I_DIR in service_worker.js tabs.css ttl_gen.js utils.js ; do 40 | cp -va $SRC_DIR/$I_DIR $DST_DIR/ 41 | done 42 | 43 | 44 | #copy Chrome related files 45 | cp -va $SRC_DIR/manifest.json $DST_DIR/ 46 | cp -va $SRC_DIR/browser.js $DST_DIR/browser.js 47 | 48 | for I_DIR in images lib; do 49 | mkdir -pv $DST_DIR/$I_DIR 50 | tar --exclude 'original' -cf - -C $SRC_DIR/$I_DIR .|tar -xf - -C $DST_DIR/$I_DIR 51 | done 52 | -------------------------------------------------------------------------------- /prepare_ff.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | EXT_DIRNAME=./OSDS_FF 3 | EXT_SRC=./src 4 | 5 | rm -rf $EXT_DIRNAME 6 | 7 | mkdir -pv $EXT_DIRNAME 8 | 9 | 10 | SRC_DIR=./ 11 | DST_DIR=$EXT_DIRNAME 12 | 13 | #copy info files 14 | for I_DIR in AUTHORS COPYING CREDITS; do 15 | cp -va $SRC_DIR/$I_DIR $DST_DIR/ 16 | done 17 | 18 | 19 | SRC_DIR=$EXT_SRC 20 | DST_DIR=$EXT_DIRNAME 21 | 22 | 23 | #copy common files 24 | for I_DIR in background.js background_web.js chat-inject.js chat-srv.js content.css converters.js datablock.js; do 25 | cp -va $SRC_DIR/$I_DIR $DST_DIR/ 26 | done 27 | 28 | for I_DIR in dataview.css frame_scan.js frame_text.js handlers.js helpers.js helpers_ui.js html_gen.js ; do 29 | cp -va $SRC_DIR/$I_DIR $DST_DIR/ 30 | done 31 | 32 | for I_DIR in oidc-webid-inject.js OidcWebid.js options.html options.js page_panel.html page_panel.js ; do 33 | cp -va $SRC_DIR/$I_DIR $DST_DIR/ 34 | done 35 | 36 | for I_DIR in panel.html panel.js settings.js sniffer.js sniffer_nano.js social_sniffer.js super_links.js ; do 37 | cp -va $SRC_DIR/$I_DIR $DST_DIR/ 38 | done 39 | 40 | for I_DIR in service_worker_ff.js tabs.css ttl_gen.js utils.js ; do 41 | cp -va $SRC_DIR/$I_DIR $DST_DIR/ 42 | done 43 | 44 | 45 | #copy Firefox related files 46 | cp -va $SRC_DIR/manifest.json.ff $DST_DIR/manifest.json 47 | cp -va $SRC_DIR/browser_ff.js $DST_DIR/browser.js 48 | 49 | for I_DIR in images lib; do 50 | mkdir -pv $DST_DIR/$I_DIR 51 | tar --exclude 'original' -cf - -C $SRC_DIR/$I_DIR .|tar -xf - -C $DST_DIR/$I_DIR 52 | done 53 | 54 | rm $DST_DIR/lib/solid-client-authn.bundle.js.map 55 | -------------------------------------------------------------------------------- /prepare_safari.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | EXT_DIRNAME=./Safari/Shared\ \(Extension\)/Resources 3 | 4 | 5 | export SRC_DIR=./ 6 | export DST_DIR="./Safari/Shared (Extension)/Resources" 7 | 8 | #copy info files 9 | for I_DIR in AUTHORS COPYING CREDITS; do 10 | cp -va $SRC_DIR/$I_DIR "$DST_DIR/" 11 | done 12 | 13 | 14 | SRC_DIR=./src 15 | 16 | 17 | #copy common files 18 | for I_DIR in background.js background_web.js chat-inject.js chat-srv.js content.css converters.js datablock.js; do 19 | cp -va $SRC_DIR/$I_DIR "$DST_DIR/" 20 | done 21 | 22 | for I_DIR in dataview.css frame_scan.js frame_text.js handlers.js helpers.js helpers_ui.js html_gen.js ; do 23 | cp -va $SRC_DIR/$I_DIR "$DST_DIR/" 24 | done 25 | 26 | for I_DIR in oidc-webid-inject.js OidcWebid.js options.html options.js page_panel.html page_panel.js ; do 27 | cp -va $SRC_DIR/$I_DIR "$DST_DIR/" 28 | done 29 | 30 | for I_DIR in panel.html panel.js settings.js sniffer.js sniffer_nano.js social_sniffer.js super_links.js ; do 31 | cp -va $SRC_DIR/$I_DIR "$DST_DIR/" 32 | done 33 | 34 | for I_DIR in service_worker_sf.js tabs.css ttl_gen.js utils.js ; do 35 | cp -va $SRC_DIR/$I_DIR "$DST_DIR/" 36 | done 37 | 38 | #copy Safari related files 39 | cp -va $SRC_DIR/manifest.json.sf "$DST_DIR/manifest.json" 40 | cp -va $SRC_DIR/browser_sf.js "$DST_DIR/browser.js" 41 | 42 | for I_DIR in images lib; do 43 | mkdir -pv "$DST_DIR/$I_DIR" 44 | tar --exclude 'original' -cf - -C $SRC_DIR/$I_DIR .|tar -xf - -C "$DST_DIR/$I_DIR" 45 | done 46 | 47 | rm "$DST_DIR/lib/solid-client-authn.bundle.js.map" 48 | 49 | -------------------------------------------------------------------------------- /src/background.html: -------------------------------------------------------------------------------- 1 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/background.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenLink Structured Data Sniffer 3 | * 4 | * Copyright (C) 2015-2021 OpenLink Software 5 | * 6 | * This project is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License as published by the 8 | * Free Software Foundation; only version 2 of the License, dated June 1991. 9 | * 10 | * This program is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, write to the Free Software Foundation, Inc., 17 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | 22 | 23 | (function () { 24 | 25 | var page_panel_url = Browser.api.runtime.getURL("page_panel.html"); 26 | 27 | 28 | async function handle_super_links_chatgpt(sender, chatgpt_req, event) 29 | { 30 | const setting = new Settings(); 31 | const curTab = sender.tab.id; 32 | 33 | try { 34 | const model = await setting.getValue("osds.chatgpt_model"); 35 | let temperature = await setting.getValue("osds.chatgpt_temp"); 36 | const token = await setting.getValue("osds.chatgpt_openai_token"); 37 | let max_tokens = await setting.getValue("osds.chatgpt_max_tokens"); 38 | 39 | try { 40 | max_tokens = parseInt(max_tokens,10); 41 | if (max_tokens <= 0) 42 | max_tokens = 4096; 43 | } catch(e) { 44 | max_tokens = 4096; 45 | } 46 | try { 47 | temperature = parseFloat(temperature).toFixed(2); 48 | temperature = parseFloat(temperature); 49 | if (temperature <0 || temperature >1) 50 | temperature = 1; 51 | } catch(e) { 52 | temperature = 1; 53 | } 54 | 55 | Browser.api.tabs.sendMessage(curTab, {cmd:'super_links_msg_show', message: 'Send OpenAI request' }); 56 | 57 | const ret = await req_openai({token, model, temperature, max_tokens, req: chatgpt_req}) 58 | if (ret.rc === 1) 59 | Browser.api.tabs.sendMessage(curTab, {cmd:"super_links_chatgpt_return", req:chatgpt_req, resp:ret.text, event}); 60 | else 61 | Browser.api.tabs.sendMessage(curTab, {cmd:"super_links_chatgpt_return", err:ret.err, event}); 62 | } 63 | finally { 64 | Browser.api.tabs.sendMessage(curTab, { cmd: 'super_links_msg_hide' }); 65 | } 66 | } 67 | 68 | 69 | Browser.api.runtime.onMessage.addListener(async function(request, sender, sendResponse) 70 | { 71 | try { 72 | if (request.cmd === "openIfHandled") 73 | { 74 | var tabId = request.tabId; 75 | var tab = await GVars.getPage(tabId); 76 | if (tab) { 77 | var url = page_panel_url+"?url="+encodeURIComponent(tab.url)+"&type="+tab.type+"&ext="+tab.ext; 78 | Browser.createTab(url); 79 | sendResponse({'cmd': request.cmd, 'opened':true, url}); 80 | return true; 81 | } 82 | else { 83 | sendResponse({'cmd': request.cmd, 'opened':false}); 84 | return true; 85 | } 86 | } 87 | else if (request.cmd === "super_links_chatgpt") 88 | { 89 | handle_super_links_chatgpt(sender, request.req, request.event); 90 | } 91 | else if (request.cmd === "actionSuperLinks") 92 | { 93 | var curTab = await getCurTab(); 94 | if (curTab.length > 0) 95 | actionSuperLinks(null, curTab[0]); 96 | } 97 | else if (request.cmd === "actionSPARQL_Upload") 98 | { 99 | var curTab = await getCurTab(); 100 | if (curTab.length > 0) 101 | actionSPARQL_Upload(null, curTab[0], request); 102 | } 103 | } catch(e) { 104 | console.log("OSDS: onMsg="+e); 105 | } 106 | 107 | }); 108 | 109 | 110 | 111 | Browser.api.runtime.onMessage.addListener(async function(request, sender, sendResponse) 112 | { 113 | try { 114 | if (request.cmd === "gpt_window_reg") { //receive that chat is opened 115 | const chat = new ChatService(); 116 | await chat.load_settings(); 117 | chat.reg_chat_window(sender.tab, request.chat_id) 118 | } 119 | else if (request.cmd === "gpt_window_unreg") { //receive that chat is opened 120 | const chat = new ChatService(); 121 | await chat.load_settings(); 122 | chat.unreg_chat_window(sender.tab) 123 | } 124 | else if (request.cmd === "gpt_page_content" && request.tabId) { // request from popup panel 125 | const chat = new ChatService(); 126 | await chat.load_settings(); 127 | chat.askChatGPT_page_content({pageUrl:request.url},{id:request.tabId}); 128 | } 129 | } catch(e) { 130 | console.log("OSDS: onMsg="+e); 131 | } 132 | 133 | }); 134 | 135 | 136 | ////////// Context Menu 137 | try { 138 | Browser.api.runtime.onInstalled.addListener((d) => { 139 | if(d.reason !== "install" && d.reason !== "update") return; 140 | 141 | Browser.api.contextMenus.create( 142 | {title: "Super Links", contexts:["page"], id: "mn-superlinks"}); 143 | 144 | Browser.api.contextMenus.create( 145 | {title: "Ask ChatGPT", contexts:["selection"], id: "mn-askLLM-sel"}); 146 | 147 | Browser.api.contextMenus.create( 148 | {title: "Ask ChatGPT for Page Content", contexts:["page"], id: "mn-askLLM-page"}); 149 | }); 150 | 151 | Browser.api.contextMenus.onClicked.addListener(async (info, tab) => { 152 | switch (info.menuItemId) { 153 | case "mn-superlinks": 154 | actionSuperLinks(info, tab); 155 | break; 156 | case "mn-askLLM-sel": 157 | { 158 | const chat = new ChatService(); 159 | await chat.load_settings(); 160 | chat.askChatGPT_selection(info, tab) 161 | } 162 | break; 163 | case "mn-askLLM-page": 164 | { 165 | const chat = new ChatService(); 166 | await chat.load_settings(); 167 | chat.askChatGPT_page_content(info, tab) 168 | } 169 | break; 170 | } 171 | }); 172 | 173 | } catch(e) { 174 | console.log(e); 175 | } 176 | 177 | 178 | 179 | async function actionSuperLinks(info, tab) { 180 | await Actions.clear(); 181 | 182 | var slinks = new SuperLinks(tab.url, tab.id); 183 | await Actions.setSuperLinks(); 184 | await slinks.save_state(); 185 | 186 | var rc = await slinks.check_login(); 187 | 188 | if (rc) { 189 | rc = await slinks.mexec(); 190 | if (rc) { 191 | await Actions.clear(); 192 | } 193 | } 194 | } 195 | 196 | //actionSPARQL_Upload(null, curTab[0], request.data, request.sparql_ep); 197 | async function actionSPARQL_Upload(info, tab, request) { 198 | await Actions.clear(); 199 | 200 | var sparql = new SPARQL_Upload(tab, request); 201 | await Actions.setSPARQL_Uploads(); 202 | await sparql.save_state(); 203 | 204 | var rc = await sparql.check_login(); 205 | 206 | if (rc) { 207 | rc = await sparql.mexec(); 208 | if (rc) { 209 | await Actions.clear(); 210 | } 211 | } 212 | } 213 | 214 | 215 | 216 | 217 | //Chrome API 218 | //wait data from extension 219 | Browser.api.runtime.onMessage.addListener(async function(request, sender, sendResponse) 220 | { 221 | try { 222 | if (request.cmd === "reset_uploads") 223 | { 224 | await Actions.clear(); 225 | } 226 | else if (request.cmd === "close_oidc_web") 227 | { 228 | var curWin = await getCurWin(); 229 | var curTab = await getCurTab(); 230 | if (request.url && curTab.length > 0 && curTab[0].windowId === curWin.id 231 | && curTab[0].url === request.url) { 232 | Browser.api.tabs.remove(curTab[0].id); 233 | } 234 | 235 | } 236 | else if (request.cmd === "close_oidc_web_slogin") 237 | { 238 | var curWin = await getCurWin(); 239 | var curTab = await getCurTab(); 240 | if (request.url && curTab.length > 0 && curTab[0].windowId === curWin.id 241 | && curTab[0].url === request.url) { 242 | Browser.api.tabs.remove(curTab[0].id); 243 | } 244 | 245 | if (await Actions.isSuperLinks()) { 246 | var slinks = new SuperLinks(); 247 | await slinks.load_state(); 248 | if (slinks && slinks.state) { 249 | var rc = await slinks.reexec(); 250 | if (rc) { 251 | await Actions.clear(); 252 | } 253 | } else { 254 | await Actions.clear(); 255 | } 256 | } 257 | else if (await Actions.isSPARQL_Uploads()) { 258 | var sparql = new SPARQL_Upload(); 259 | await sparql.load_state(); 260 | if (sparql && sparql.state) { 261 | var rc = await sparql.reexec(); 262 | if (rc) 263 | await Actions.clear(); 264 | } else { 265 | await Actions.clear(); 266 | } 267 | } 268 | 269 | } 270 | else if (request.cmd === "osds_popup_retry") 271 | { 272 | if (await Actions.isSPARQL_Uploads()) { 273 | var sparql = new SPARQL_Upload(); 274 | await sparql.load_state(); 275 | if (sparql && sparql.state === "init") { 276 | var rc = await sparql.reexec(); 277 | if (rc) 278 | await Actions.clear(); 279 | } else { 280 | await Actions.clear(); 281 | } 282 | } 283 | } 284 | else if (request.cmd === "osds_popup_cancel") 285 | { 286 | if (await Actions.isSPARQL_Uploads()) { 287 | await Actions.clear(); 288 | } 289 | } 290 | 291 | } catch(e) { 292 | console.log("OSDS: onMsg="+e); 293 | } 294 | 295 | }); 296 | 297 | Browser.api.tabs.onRemoved.addListener(async function(tabId, removed) { 298 | await GVars.deletePage(tabId); 299 | }) 300 | 301 | })(); 302 | -------------------------------------------------------------------------------- /src/browser.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenLink Structured Data Sniffer 3 | * 4 | * Copyright (C) 2015-2021 OpenLink Software 5 | * 6 | * This project is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License as published by the 8 | * Free Software Foundation; only version 2 of the License, dated June 1991. 9 | * 10 | * This program is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, write to the Free Software Foundation, Inc., 17 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | var Browser = { 22 | is_chrome: true, 23 | is_ff: false, 24 | is_safari: false, 25 | is_chrome_v3: true, 26 | is_ff_v3: false, 27 | 28 | api: null, 29 | 30 | openTab : function(uri, tab_index) { 31 | if (Browser.is_safari) { 32 | if (tab_index!==undefined) 33 | Browser.api.tabs.create({url:uri, index:tab_index+1 }); 34 | else 35 | Browser.api.tabs.getCurrent( 36 | function(tab) { 37 | if (tab!==undefined) 38 | Browser.api.tabs.create({url:uri, index:tab.index+1 }); 39 | else 40 | Browser.api.tabs.create({url:uri}); 41 | } 42 | ) 43 | }else 44 | window.open(uri); 45 | }, 46 | createTab : function(url) { 47 | if (Browser.is_ff || Browser.is_chrome_v3 || is_safari) { 48 | Browser.api.tabs.create({url:url}); 49 | } 50 | else if (window && window.open) 51 | window.open(url); 52 | else 53 | Browser.api.tabs.create({url:url}); 54 | }, 55 | 56 | throbber : 'R0lGODlhEAAQAPMAADMzM0xMTOXl5WZmZszMzH9/f7KyspmZmUxMTH9/f5mZmbKysszMzOXl5f///wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAOACwAAAAAEAAQAAAErdA555xzADjnnIPOOeeccwAA4Bx0zjnnXAgOAACgE8I551wIITgAgRNCCOecCyEE6JxzQgjhnHMuwOCcc84J4ZxzAw7nnHPOOecIcXCMMZxzzjnnCIGEjDGGc8455xwkhBA3hnPOOeegc44Q55wrxTkHnXPGOOecK6UU6JxzxhjjnHOlwFLcOc4YY5xzDrpS3DnnOGOcc9A555w75xznnIPOOeecc+4c5xx0zrkIACH5BAkKAA4ALAAAAAAQABAAAASt0DnnnHMhOOecg84555xzIYTgHHTOOefcGC6EEKADwDnn3BhjuACDAwAA55wbYwzonHMAAOCcc27A4ZxzzgHgnHMFFuecc84554RwsJRSnHPOOeeEgEKUUopzzjnnHBRCCFeKc84556BzTgjnnDvHOQedc4Q455w75xzonHOEEOKcc+fAc5wxjhBCnHMOunOcMcY4Qpxz0DnnnDPGGOecg84555xzzhjnHHTOuQgAIfkECQoADgAsAAAAABAAEAAABK3QOeecc2M455yDzjnnnHNjjOEcdM4551wpbowxoAPAOedcKaW4AYcDAADnnCulFOiccwAA4JxzrsDinHPOAeCccwce55xzzjnnAHDwnHOcc8455wCAAJxzjnPOOeccBAAAd45zzjnnoHMOAOecM8Y5B51zQjjnnDPGGOicc0II4ZxzxkBjHCFOCCGccw46YxwhhDghnHPQOeecI4QQ55yDzjnnnHOOEOccdM65CAAh+QQJCgAOACwAAAAAEAAQAAAErdA555xzpTjnnIPOOeecc6WU4hx0zjnn3DmulFKgG8M559w557gCixtjDOecO+cc6JxzY4zhnHPuwOOcc86N4ZxzBhrnnHPOOedCcNAYY5xzzjnnQoAhGGOMc8455xwMIQRnjHPOOeegcy4E55wjxDkHnXMAOOecI4QQ6JxzAADgnHOEQEKcEA4AAJxzDjpCnBBCOACcc9A555wTQgjnnIPOOeecc04I5xx0zrkIACH5BAkKAA4ALAAAAAAQABAAAASt0DnnnHPnOOecg84555xz55zjHHTOOeecMe6cc6ArxTnnnDHGuAOPK6UU55wzxhjonHOllOKcc85A45xzzpXinHMEEuecc84558ZwkBBCnHPOOefGgGMQQohzzjnnHBxjDEeIc84556BzbgznnBPCOQedcyE455wTQgjonHMhhOCcc0JAIRwALoQQnHMOOiEcAAC4EJxz0DnnnAMAAOecg84555xzDgDnHHTOuQgAIfkECQoADgAsAAAAABAAEAAABK3QOeecc8Y455yDzjnnnHPGGOMcdM455xwhzhhjoDvHOeccIYQ4A4075xznnCOEEOicc+ec45xzjkDinHPOneOccwIK55xzzjnnSnFQCCGcc84550qBpQghhHPOOeccLKUUJ4RzzjnnoHOuFOecA8A5B51zYzjnnAMAAOicc2OM4ZxzAEAAXAhujDGccw46AFwIIbgxnHPQOeecCyEE55yDzjnnnHMuBOccdM65CAAh+QQJCgAOACwAAAAAEAAQAAAErdA555xzhDjnnIPOOeecc4QQ4hx0zjnnnBCOEEKgM8Y555wQQjgCiTPGGOecE0II6JxzxhjjnHNOQOGcc84Z45xzAALnnHPOOefOcRAAAJxzzjnnzoHnAACAc8455xw85xwHgHPOOeegc+4c55wLwTkHnXOlOOecCyEE6JxzpZTinHMhwBDcGK6UUpxzDroQ3BhjuFKcc9A555wbYwznnIPOOeecc24M5xx0zrkIACH5BAkKAA4ALAAAAAAQABAAAASt0DnnnHNCOOecg84555xzQgjhHHTOOeccAE4IIaAjxDnnHAAAOAGFI4QQ55wDAADonHOEEOKccw5A4JxzzhHinHMBBuecc84554xxMIQQnHPOOeeMgcaEEIJzzjnnHDTGGBeCc84556BzzhjnnBvDOQedc+c455wbYwzonHPnnOOcc2PAMVwp7pxznHMOujFcKaW4c5xz0DnnnCulFOecg84555xzrhTnHHTOuQgAOw==' 57 | 58 | } 59 | 60 | try { 61 | Browser.api = (Browser.is_chrome) ? chrome : browser; 62 | } catch(e) {} 63 | -------------------------------------------------------------------------------- /src/browser_ff.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenLink Structured Data Sniffer 3 | * 4 | * Copyright (C) 2015-2021 OpenLink Software 5 | * 6 | * This project is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License as published by the 8 | * Free Software Foundation; only version 2 of the License, dated June 1991. 9 | * 10 | * This program is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, write to the Free Software Foundation, Inc., 17 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | var Browser = { 22 | is_chrome: false, 23 | is_ff: true, 24 | is_safari: false, 25 | is_chrome_v3: false, 26 | is_ff_v3: true, 27 | 28 | api: null, 29 | 30 | openTab : function(uri, tab_index) { 31 | if (Browser.is_safari) { 32 | if (tab_index!==undefined) 33 | Browser.api.tabs.create({url:uri, index:tab_index+1 }); 34 | else 35 | Browser.api.tabs.getCurrent( 36 | function(tab) { 37 | if (tab!==undefined) 38 | Browser.api.tabs.create({url:uri, index:tab.index+1 }); 39 | else 40 | Browser.api.tabs.create({url:uri}); 41 | } 42 | ) 43 | }else 44 | window.open(uri); 45 | }, 46 | createTab : function(url) { 47 | if (Browser.is_ff || Browser.is_chrome_v3 || Browser.is_ff_v3) { 48 | Browser.api.tabs.create({url:url}); 49 | } 50 | else if (window && window.open) 51 | window.open(url); 52 | else 53 | Browser.api.tabs.create({url:url}); 54 | }, 55 | 56 | throbber : 'R0lGODlhEAAQAPMAADMzM0xMTOXl5WZmZszMzH9/f7KyspmZmUxMTH9/f5mZmbKysszMzOXl5f///wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAOACwAAAAAEAAQAAAErdA555xzADjnnIPOOeeccwAA4Bx0zjnnXAgOAACgE8I551wIITgAgRNCCOecCyEE6JxzQgjhnHMuwOCcc84J4ZxzAw7nnHPOOecIcXCMMZxzzjnnCIGEjDGGc8455xwkhBA3hnPOOeegc44Q55wrxTkHnXPGOOecK6UU6JxzxhjjnHOlwFLcOc4YY5xzDrpS3DnnOGOcc9A555w75xznnIPOOeecc+4c5xx0zrkIACH5BAkKAA4ALAAAAAAQABAAAASt0DnnnHMhOOecg84555xzIYTgHHTOOefcGC6EEKADwDnn3BhjuACDAwAA55wbYwzonHMAAOCcc27A4ZxzzgHgnHMFFuecc84554RwsJRSnHPOOeeEgEKUUopzzjnnHBRCCFeKc84556BzTgjnnDvHOQedc4Q455w75xzonHOEEOKcc+fAc5wxjhBCnHMOunOcMcY4Qpxz0DnnnDPGGOecg84555xzzhjnHHTOuQgAIfkECQoADgAsAAAAABAAEAAABK3QOeecc2M455yDzjnnnHNjjOEcdM4551wpbowxoAPAOedcKaW4AYcDAADnnCulFOiccwAA4JxzrsDinHPOAeCccwce55xzzjnnAHDwnHOcc8455wCAAJxzjnPOOeccBAAAd45zzjnnoHMOAOecM8Y5B51zQjjnnDPGGOicc0II4ZxzxkBjHCFOCCGccw46YxwhhDghnHPQOeecI4QQ55yDzjnnnHOOEOccdM65CAAh+QQJCgAOACwAAAAAEAAQAAAErdA555xzpTjnnIPOOeecc6WU4hx0zjnn3DmulFKgG8M559w557gCixtjDOecO+cc6JxzY4zhnHPuwOOcc86N4ZxzBhrnnHPOOedCcNAYY5xzzjnnQoAhGGOMc8455xwMIQRnjHPOOeegcy4E55wjxDkHnXMAOOecI4QQ6JxzAADgnHOEQEKcEA4AAJxzDjpCnBBCOACcc9A555wTQgjnnIPOOeecc04I5xx0zrkIACH5BAkKAA4ALAAAAAAQABAAAASt0DnnnHPnOOecg84555xz55zjHHTOOeecMe6cc6ArxTnnnDHGuAOPK6UU55wzxhjonHOllOKcc85A45xzzpXinHMEEuecc84558ZwkBBCnHPOOefGgGMQQohzzjnnHBxjDEeIc84556BzbgznnBPCOQedcyE455wTQgjonHMhhOCcc0JAIRwALoQQnHMOOiEcAAC4EJxz0DnnnAMAAOecg84555xzDgDnHHTOuQgAIfkECQoADgAsAAAAABAAEAAABK3QOeecc8Y455yDzjnnnHPGGOMcdM455xwhzhhjoDvHOeccIYQ4A4075xznnCOEEOicc+ec45xzjkDinHPOneOccwIK55xzzjnnSnFQCCGcc84550qBpQghhHPOOeccLKUUJ4RzzjnnoHOuFOecA8A5B51zYzjnnAMAAOicc2OM4ZxzAEAAXAhujDGccw46AFwIIbgxnHPQOeecCyEE55yDzjnnnHMuBOccdM65CAAh+QQJCgAOACwAAAAAEAAQAAAErdA555xzhDjnnIPOOeecc4QQ4hx0zjnnnBCOEEKgM8Y555wQQjgCiTPGGOecE0II6JxzxhjjnHNOQOGcc84Z45xzAALnnHPOOefOcRAAAJxzzjnnzoHnAACAc8455xw85xwHgHPOOeegc+4c55wLwTkHnXOlOOecCyEE6JxzpZTinHMhwBDcGK6UUpxzDroQ3BhjuFKcc9A555wbYwznnIPOOeecc24M5xx0zrkIACH5BAkKAA4ALAAAAAAQABAAAASt0DnnnHNCOOecg84555xzQgjhHHTOOeccAE4IIaAjxDnnHAAAOAGFI4QQ55wDAADonHOEEOKccw5A4JxzzhHinHMBBuecc84554xxMIQQnHPOOeeMgcaEEIJzzjnnHDTGGBeCc84556BzzhjnnBvDOQedc+c455wbYwzonHPnnOOcc2PAMVwp7pxznHMOujFcKaW4c5xz0DnnnCulFOecg84555xzrhTnHHTOuQgAOw==' 57 | 58 | } 59 | 60 | try { 61 | Browser.api = (Browser.is_chrome) ? chrome : browser; 62 | } catch(e) {} 63 | -------------------------------------------------------------------------------- /src/browser_sf.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenLink Structured Data Sniffer 3 | * 4 | * Copyright (C) 2015-2021 OpenLink Software 5 | * 6 | * This project is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License as published by the 8 | * Free Software Foundation; only version 2 of the License, dated June 1991. 9 | * 10 | * This program is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, write to the Free Software Foundation, Inc., 17 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | var Browser = { 22 | is_chrome: false, 23 | is_ff: true, 24 | is_safari: true, 25 | is_chrome_v3: false, 26 | is_ff_v3: false, 27 | 28 | api: null, 29 | 30 | openTab : function(uri, tab_index) { 31 | if (Browser.is_safari) { 32 | if (tab_index!==undefined) 33 | Browser.api.tabs.create({url:uri, index:tab_index+1 }); 34 | else 35 | Browser.api.tabs.getCurrent( 36 | function(tab) { 37 | if (tab!==undefined) 38 | Browser.api.tabs.create({url:uri, index:tab.index+1 }); 39 | else 40 | Browser.api.tabs.create({url:uri}); 41 | } 42 | ) 43 | }else 44 | window.open(uri); 45 | }, 46 | createTab : function(url) { 47 | if (Browser.is_ff || Browser.is_chrome_v3 || is_safari) { 48 | Browser.api.tabs.create({url:url}); 49 | } 50 | else if (window && window.open) 51 | window.open(url); 52 | else 53 | Browser.api.tabs.create({url:url}); 54 | }, 55 | 56 | throbber : 'R0lGODlhEAAQAPMAADMzM0xMTOXl5WZmZszMzH9/f7KyspmZmUxMTH9/f5mZmbKysszMzOXl5f///wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJCgAOACwAAAAAEAAQAAAErdA555xzADjnnIPOOeeccwAA4Bx0zjnnXAgOAACgE8I551wIITgAgRNCCOecCyEE6JxzQgjhnHMuwOCcc84J4ZxzAw7nnHPOOecIcXCMMZxzzjnnCIGEjDGGc8455xwkhBA3hnPOOeegc44Q55wrxTkHnXPGOOecK6UU6JxzxhjjnHOlwFLcOc4YY5xzDrpS3DnnOGOcc9A555w75xznnIPOOeecc+4c5xx0zrkIACH5BAkKAA4ALAAAAAAQABAAAASt0DnnnHMhOOecg84555xzIYTgHHTOOefcGC6EEKADwDnn3BhjuACDAwAA55wbYwzonHMAAOCcc27A4ZxzzgHgnHMFFuecc84554RwsJRSnHPOOeeEgEKUUopzzjnnHBRCCFeKc84556BzTgjnnDvHOQedc4Q455w75xzonHOEEOKcc+fAc5wxjhBCnHMOunOcMcY4Qpxz0DnnnDPGGOecg84555xzzhjnHHTOuQgAIfkECQoADgAsAAAAABAAEAAABK3QOeecc2M455yDzjnnnHNjjOEcdM4551wpbowxoAPAOedcKaW4AYcDAADnnCulFOiccwAA4JxzrsDinHPOAeCccwce55xzzjnnAHDwnHOcc8455wCAAJxzjnPOOeccBAAAd45zzjnnoHMOAOecM8Y5B51zQjjnnDPGGOicc0II4ZxzxkBjHCFOCCGccw46YxwhhDghnHPQOeecI4QQ55yDzjnnnHOOEOccdM65CAAh+QQJCgAOACwAAAAAEAAQAAAErdA555xzpTjnnIPOOeecc6WU4hx0zjnn3DmulFKgG8M559w557gCixtjDOecO+cc6JxzY4zhnHPuwOOcc86N4ZxzBhrnnHPOOedCcNAYY5xzzjnnQoAhGGOMc8455xwMIQRnjHPOOeegcy4E55wjxDkHnXMAOOecI4QQ6JxzAADgnHOEQEKcEA4AAJxzDjpCnBBCOACcc9A555wTQgjnnIPOOeecc04I5xx0zrkIACH5BAkKAA4ALAAAAAAQABAAAASt0DnnnHPnOOecg84555xz55zjHHTOOeecMe6cc6ArxTnnnDHGuAOPK6UU55wzxhjonHOllOKcc85A45xzzpXinHMEEuecc84558ZwkBBCnHPOOefGgGMQQohzzjnnHBxjDEeIc84556BzbgznnBPCOQedcyE455wTQgjonHMhhOCcc0JAIRwALoQQnHMOOiEcAAC4EJxz0DnnnAMAAOecg84555xzDgDnHHTOuQgAIfkECQoADgAsAAAAABAAEAAABK3QOeecc8Y455yDzjnnnHPGGOMcdM455xwhzhhjoDvHOeccIYQ4A4075xznnCOEEOicc+ec45xzjkDinHPOneOccwIK55xzzjnnSnFQCCGcc84550qBpQghhHPOOeccLKUUJ4RzzjnnoHOuFOecA8A5B51zYzjnnAMAAOicc2OM4ZxzAEAAXAhujDGccw46AFwIIbgxnHPQOeecCyEE55yDzjnnnHMuBOccdM65CAAh+QQJCgAOACwAAAAAEAAQAAAErdA555xzhDjnnIPOOeecc4QQ4hx0zjnnnBCOEEKgM8Y555wQQjgCiTPGGOecE0II6JxzxhjjnHNOQOGcc84Z45xzAALnnHPOOefOcRAAAJxzzjnnzoHnAACAc8455xw85xwHgHPOOeegc+4c55wLwTkHnXOlOOecCyEE6JxzpZTinHMhwBDcGK6UUpxzDroQ3BhjuFKcc9A555wbYwznnIPOOeecc24M5xx0zrkIACH5BAkKAA4ALAAAAAAQABAAAASt0DnnnHNCOOecg84555xzQgjhHHTOOeccAE4IIaAjxDnnHAAAOAGFI4QQ55wDAADonHOEEOKccw5A4JxzzhHinHMBBuecc84554xxMIQQnHPOOeeMgcaEEIJzzjnnHDTGGBeCc84556BzzhjnnBvDOQedc+c455wbYwzonHPnnOOcc2PAMVwp7pxznHMOujFcKaW4c5xz0DnnnCulFOecg84555xzrhTnHHTOuQgAOw==' 57 | 58 | } 59 | 60 | try { 61 | Browser.api = (Browser.is_chrome) ? chrome : browser; 62 | } catch(e) {} 63 | 64 | -------------------------------------------------------------------------------- /src/chat-srv.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenLink Structured Data Sniffer 3 | * 4 | * Copyright (C) 2015-2021 OpenLink Software 5 | * 6 | * This project is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License as published by the 8 | * Free Software Foundation; only version 2 of the License, dated June 1991. 9 | * 10 | * This program is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, write to the Free Software Foundation, Inc., 17 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | class ChatService { 22 | constructor() 23 | { 24 | this.tab = {}; 25 | this.chatTabSrv = null; 26 | this.waited_ask = null; 27 | this.timeout = 5000 28 | this.prompt_id = null; 29 | this.prompt_url = null; 30 | this.prompt_in_new_window = false; 31 | this.setting = new Settings(); 32 | } 33 | 34 | async saveState() 35 | { 36 | const v = { 37 | id: this.tab ? this.tab.id : '', 38 | winId: this.tab ? this.tab.winId : '' 39 | } 40 | try { 41 | await this.setting.setValue('g.ChatTab', JSON.stringify(v)); 42 | await this.setting.setValue('g.ChatTabAsk', JSON.stringify(this.waited_ask || '')); 43 | } catch(_) { 44 | } 45 | } 46 | 47 | async loadState() 48 | { 49 | try { 50 | var v = await this.setting.getValue('g.ChatTab'); 51 | if (v) 52 | this.tab = JSON.parse(v); 53 | 54 | v = await this.setting.getValue('g.ChatTabAsk'); 55 | if (v) 56 | this.waited_ask = JSON.parse(v); 57 | else 58 | this.waited_ask = null; 59 | } catch(_) { 60 | } 61 | } 62 | 63 | async load_settings() 64 | { 65 | this.prompt_id = await this.setting.getValue('ext.osds.chat-srv'); 66 | try { 67 | const s = await this.setting.getValue('ext.osds.def_prompt_inject') 68 | const chat_list = JSON.parse(s); 69 | const v = chat_list[this.prompt_id]; 70 | if (!v) { 71 | alert('Error:\n Could not find "'+this.prompt_id+'" item in new LLM Server\'s settings!\n Update value for "Chat Service" in settings') 72 | return; 73 | } 74 | this.prompt_url = v['url'] ? v['url'] : null; 75 | this.prompt_in_new_window = v['prompt_in_new_window'] ? v['prompt_in_new_window'] : false; 76 | } catch(e) { 77 | console.log(e); 78 | this.prompt_id = null; 79 | } 80 | await this.loadState(); 81 | } 82 | 83 | async reg_chat_window(tab, chat_id) 84 | { 85 | if (chat_id !== this.prompt_id) 86 | return; 87 | 88 | this.tab = {'id': tab.id, 'winId': tab.windowId}; 89 | await this.saveState(); 90 | //send tabId, winId back to Chat Window 91 | Browser.api.tabs.sendMessage(this.tab.id, {cmd:"gpt_win_tab", tabId:this.tab.id, winId:this.tab.winId}); 92 | 93 | if (this.waited_ask) { 94 | this.activateChatWin(tab, this.waited_ask) 95 | this.waited_ask = null; 96 | await this.saveState(); 97 | } 98 | } 99 | 100 | async unreg_chat_window(tab) 101 | { 102 | if (this.tab && this.tab.id === tab.id) { 103 | this.tab = {}; 104 | this.waited_ask = null 105 | await this.saveState(); 106 | } 107 | } 108 | 109 | async activateChatWin(tab, ask) 110 | { 111 | this.tab = {'id': tab.id, 'winId': tab.windowId}; 112 | await this.saveState(); 113 | 114 | if (Browser.is_ff || Browser.is_chrome_v3) { 115 | await Browser.api.windows.update(this.tab.winId, {focused: true}); 116 | await Browser.api.tabs.update(this.tab.id, {active: true}); 117 | } 118 | else { 119 | Browser.api.windows.update(this.tab.winId, {focused: true}, (window) => { 120 | Browser.api.tabs.update(this.tab.id, {active: true}) 121 | }) 122 | } 123 | 124 | if (this.timeout > 0) 125 | await sleep(this.timeout); 126 | 127 | const model = await this.setting.getValue('ext.osds.gpt-model'); 128 | var max_len = parseInt(await this.setting.getValue('ext.osds.gpt-tokens'), 10); 129 | if (max_len == 0) 130 | max_len = 32000; 131 | 132 | ///gpt-35 max_tokens = 4096 133 | // gpt4 max-tokens = 8192 // 32768 134 | const myprompt = await this.setting.getValue('ext.osds.prompt'); 135 | 136 | var prompt_query = this.setting.def_prompt_query_jsonld; 137 | 138 | if (myprompt) { 139 | if (myprompt.myid === 'jsonld') 140 | prompt_query = this.setting.def_prompt_query_jsonld; 141 | else if (myprompt.myid === 'turtle') 142 | prompt_query = this.setting.def_prompt_query_turtle; 143 | else if (myprompt?.text.length > 1) 144 | prompt_query = myprompt.text; 145 | } 146 | 147 | prompt_query = prompt_query.replace("{page_url}", ask.url); 148 | var text = ask.text; 149 | 150 | if (prompt_query.length + text.length > max_len) 151 | text = text.substring(0, Math.max(1, max_len - prompt_query.length)); 152 | 153 | prompt_query = prompt_query.replace("{selected_text}", text); 154 | 155 | Browser.api.tabs.sendMessage(tab.id, {cmd:"gpt_prompt", text:prompt_query}); 156 | } 157 | 158 | 159 | async openChatWin() 160 | { 161 | if (this.prompt_id && this.prompt_url) { 162 | // Open GPT window 163 | Browser.createTab(this.prompt_url); 164 | } 165 | } 166 | 167 | 168 | async askChatGPT(ask, tab, mode) 169 | { 170 | const self = this; 171 | ask["mode"] = mode; 172 | 173 | await this.load_settings(); 174 | 175 | if (this.chatTabSrv && this.chatTabSrv !== this.prompt_id) { 176 | this.chatTabSrv = null; 177 | this.tab = {}; 178 | await this.saveState(); 179 | } 180 | 181 | async function new_llm_win() { 182 | self.waited_ask = ask; 183 | await self.saveState(); 184 | self.openChatWin(); 185 | } 186 | 187 | async function handle_resp(resp) 188 | { 189 | if (Browser.api.runtime.lastError) { 190 | new_llm_win(); 191 | return; 192 | } 193 | 194 | if (resp && resp.ping === 1 && resp.chat_id === self.prompt_id) { 195 | 196 | // GPT window opened 197 | if (!self.prompt_in_new_window && resp.winId && resp.tabId) { 198 | self.activateChatWin({windowId:resp.winId, id:resp.tabId}, ask); 199 | } 200 | else { 201 | self.waited_ask = ask; 202 | await self.saveState(); 203 | self.openChatWin(); 204 | } 205 | } 206 | else { 207 | self.waited_ask = ask; 208 | await self.saveState(); 209 | self.openChatWin(); 210 | } 211 | } 212 | 213 | if (this.tab && this.tab.id) { 214 | if (Browser.is_ff || Browser.is_chrome_v3) { 215 | try { 216 | const resp = await Browser.api.tabs.sendMessage(this.tab.id, {cmd:"gpt_ping"}); 217 | handle_resp(resp); 218 | } catch(ex) { 219 | console.log(ex); 220 | new_llm_win(); 221 | } 222 | } 223 | else { 224 | try { 225 | Browser.api.tabs.sendMessage(this.tab.id, {cmd:"gpt_ping"}, handle_resp); 226 | } catch(ex) { 227 | console.log(ex); 228 | } 229 | } 230 | } 231 | else { 232 | new_llm_win(); 233 | } 234 | } 235 | 236 | 237 | askChatGPT_selection(info, tab) 238 | { 239 | // send text to ChatService 240 | this.askChatGPT({text:info.selectionText, url:info.pageUrl}, tab, 'selection'); 241 | } 242 | 243 | async askChatGPT_page_content(info, tab) 244 | { 245 | const self = this; 246 | let page_text = ""; 247 | 248 | function handle_frames(rc) 249 | { 250 | if (rc && rc.length > 0) 251 | self.askChatGPT({text:rc.join('\n'), url:info.pageUrl}, tab, 'content'); 252 | else 253 | self.askChatGPT({text:page_text, url:info.pageUrl}, tab, 'content'); 254 | } 255 | 256 | async function scan_frames() 257 | { 258 | if (Browser.is_chrome_v3 || Browser.is_ff_v3 || Browser.is_safari) { 259 | let frames = await Browser.api.scripting.executeScript({ 260 | target: {tabId: tab.id, allFrames:true}, 261 | injectImmediately: true, 262 | files: ['frame_scan.js'] 263 | }); 264 | let lst = []; 265 | for(var v of frames) 266 | lst.push(v.result); 267 | handle_frames(lst); 268 | } 269 | else 270 | Browser.api.tabs.executeScript(tab.id, {file:"frame_scan.js", allFrames:true, runAt: 'document_start'}, handle_frames); 271 | } 272 | 273 | async function handle_resp(resp) 274 | { 275 | if (Browser.api.runtime.lastError) 276 | return; 277 | // content received send it to ChatService 278 | if (resp && resp.page_content) { 279 | if (resp.dom && resp.dom===1 && resp.frames>0) { 280 | page_text = resp.page_content; 281 | await scan_frames(); 282 | } 283 | else 284 | self.askChatGPT({text:resp.page_content, url:info.pageUrl}, tab, 'content'); 285 | 286 | } 287 | } 288 | 289 | // request page content from page content script 290 | if (Browser.is_ff || Browser.is_chrome_v3) 291 | Browser.api.tabs.sendMessage(tab.id, {cmd:"page_content"}) 292 | .then(resp => { handle_resp(resp)}) 293 | .catch(err => { 294 | console.log(err); 295 | }); 296 | else 297 | Browser.api.tabs.sendMessage(tab.id, {cmd:"page_content"}, handle_resp); 298 | } 299 | } 300 | -------------------------------------------------------------------------------- /src/content.css: -------------------------------------------------------------------------------- 1 | .osds_revert_css { 2 | all: revert; 3 | } 4 | 5 | .osds_popup { 6 | all: initial; 7 | position: fixed !important; 8 | display: none; 9 | border: 2px solid #000 !important; 10 | border-radius: 4px !important; 11 | width: 510px; 12 | top:100px !important; 13 | left: 20px !important; 14 | background: #fff !important; 15 | color: black !important; 16 | z-index: 2147483647 !important; 17 | marging: 2px !important; 18 | marging-bottom: 10px !important; 19 | font-family: Arial, Helvetica, sans-serif !important; 20 | line-height: normal !important; 21 | } 22 | .osds_popup-title { 23 | width: 100% !important; 24 | height: 18px !important; 25 | display: flex; 26 | background-color: #0000a0 !important; 27 | color: white !important; 28 | border-bottom: 1px solid #000 !important; 29 | position: relative !important; 30 | cursor: move !important; 31 | font-size: 14px !important; 32 | text-align: center; 33 | } 34 | 35 | .osds_popup-content { 36 | height: calc(100% - 10px - 10px - 18px) !important; 37 | overflow: auto !important; 38 | padding: 10px 10px 10px 10px !important; 39 | background: khaki !important; 40 | display:flex !important; 41 | flex-direction: column !important; 42 | } 43 | 44 | .osds_popup_msg { 45 | margin: 10px 0px !important; 46 | } 47 | 48 | .osds_popup_btn { 49 | min-width:60px !important; 50 | margin-left: 10px !important; 51 | } 52 | 53 | .osds_popup_btns { 54 | margin:auto !important; 55 | } 56 | 57 | 58 | 59 | .super_links_msg { 60 | all: initial; 61 | display: none; 62 | line-height: normal !important; 63 | flex-direction: row !important; 64 | position: fixed !important; 65 | border: 2px solid #000 !important; 66 | border-radius: 2px !important; 67 | width: 200px !important; 68 | height: 20px !important; 69 | top:4px !important; 70 | left: 4px !important; 71 | background: khaki !important; 72 | color: black !important; 73 | z-index: 2147483647 !important; 74 | padding: 10px 10px 10px 20px !important; 75 | font-family: Arial, Helvetica, sans-serif !important; 76 | font-size: 14px !important; 77 | box-sizing: content-box !important; 78 | } 79 | 80 | .super_links_img { 81 | width: 16px !important; 82 | height: 16px !important; 83 | } 84 | 85 | 86 | .super_links_popup { 87 | all: initial; 88 | position: absolute; 89 | display: none; 90 | border: 2px solid #000 !important; 91 | border-radius: 4px !important; 92 | width: 910px; 93 | height: 305px; 94 | background: #fff !important; 95 | color: black !important; 96 | z-index: 2147483647 !important; 97 | marging: 2px !important; 98 | marging-bottom: 10px !important; 99 | font-family: Arial, Helvetica, sans-serif !important; 100 | line-height: normal !important; 101 | } 102 | .super_links_chatgpt { 103 | all: initial; 104 | position: absolute; 105 | display: none; 106 | border: 2px solid #000 !important; 107 | border-radius: 4px !important; 108 | width: 900px; 109 | height: 400px; 110 | background: #fff !important; 111 | color: black !important; 112 | z-index: 2147483647 !important; 113 | marging: 2px !important; 114 | marging-bottom: 10px !important; 115 | font-family: Arial, Helvetica, sans-serif !important; 116 | line-height: normal !important; 117 | } 118 | .super_links_popup-title, .super_links_chatgpt-title{ 119 | width: 100% !important; 120 | height: 18px !important; 121 | display: flex; 122 | color: white !important; 123 | border-bottom: 1px solid #000 !important; 124 | position: relative !important; 125 | cursor: move !important; 126 | font-size: 14px !important; 127 | } 128 | .super_links_popup-title{ 129 | background-color: #0000a0 !important; 130 | } 131 | .super_links_chatgpt-title{ 132 | background: #6c7ae0 !important; 133 | } 134 | 135 | 136 | .super_links_popup-content { 137 | width: 100% !important; 138 | height: calc(100% - 10px - 16px - 6px) !important; 139 | overflow: auto !important; 140 | } 141 | .super_links_chatgpt-content { 142 | width: 100% !important; 143 | height: calc(100% - 20px) !important; 144 | /*overflow: hidden !important;*/ 145 | overflow: auto !important; 146 | } 147 | .super_links_chatgpt-content-text { 148 | width: 100% !important; 149 | height: 100% !important; 150 | overflow: hidden !important; 151 | /*overflow: auto !important;*/ 152 | } 153 | 154 | #super_links_snackbar { 155 | visibility: hidden; 156 | min-width: 250px !important; 157 | margin-left: -125px !important; 158 | background-color: red !important; 159 | color: yellow !important; 160 | text-align: center !important; 161 | border-radius: 2px !important; 162 | padding: 16px !important; 163 | position: fixed !important; 164 | z-index: 1 !important; 165 | left: 50% !important; 166 | bottom: 30px !important; 167 | font-size: 17px !important; 168 | } 169 | 170 | #super_links_snackbar.show { 171 | visibility: visible; 172 | -webkit-animation: fadein 0.5s, fadeout 0.5s 5s !important; 173 | animation: fadein 0.5s, fadeout 0.5s 5s !important; 174 | } 175 | 176 | 177 | a.super_link_mark, 178 | a:link.super_link_mark, 179 | a:active.superlink, 180 | a:visited.superlink, 181 | .super_link_mark 182 | { 183 | color: green !important; 184 | background: yellow !important; 185 | } 186 | 187 | 188 | .super_links_popup_close, .super_links_chatgpt_close { 189 | background: #606061 !important; 190 | color: #FFFFFF !important; 191 | line-height: 20px !important; 192 | position: absolute !important; 193 | top:-3px !important; 194 | right: -3px !important; 195 | width: 20px !important; 196 | text-align: center !important; 197 | text-decoration: none !important; 198 | font-weight: bold !important; 199 | -webkit-border-radius: 4px !important; 200 | -moz-border-radius: 4px !important; 201 | border-radius: 4px !important; 202 | -moz-box-shadow: 1px 1px 3px #000 !important; 203 | -webkit-box-shadow: 1px 1px 3px #000 !important; 204 | box-shadow: 1px 1px 3px #000 !important; 205 | } 206 | .super_links_popup_close:hover, super_links_chatgpt_close:hover { background: #00d9ff !important; } 207 | 208 | table.super_links_table a { color: blue !important; text-decoration:underline !important; } 209 | table.super_links_table a:link { color: blue !important; } 210 | table.super_links_table a:visited { color: purple !important; } 211 | table.super_links_table a:hover { color: blue !important; } 212 | table.super_links_table a:active { color: blue !important; } 213 | 214 | 215 | table.super_links_table { 216 | font-family: 'trebuchet MS' , 'Lucida sans' , Arial !important; 217 | font-size: 13px !important; 218 | min-width: 100% !important; 219 | width: auto !important; 220 | flex: 1 !important; 221 | display: grid; 222 | border-collapse: collapse !important; 223 | /* These are just initial values which are overriden using JavaScript when a column is resized */ 224 | grid-template-columns: 225 | minmax(100px, 1.5fr) 226 | minmax(100px, 2.5fr) 227 | minmax(100px, 4fr) 228 | minmax(100px, 2fr); 229 | } 230 | 231 | table.super_links_table thead, 232 | table.super_links_table tbody, 233 | table.super_links_table tr { 234 | display: contents !important; 235 | } 236 | 237 | table.super_links_table th, 238 | table.super_links_table td { 239 | padding: 5px !important; 240 | overflow: hidden !important; 241 | text-overflow: ellipsis !important; 242 | white-space: nowrap !important; 243 | border-top: 1px solid #dddddd !important; 244 | border-left: 1px solid #dddddd !important; 245 | } 246 | 247 | table.super_links_table th { 248 | position: sticky !important; 249 | top: 0 !important; 250 | background: #6c7ae0 !important; 251 | text-align: left !important; 252 | font-weight: bold !important; 253 | color: white !important; 254 | } 255 | 256 | 257 | .super_links_table-resize-handle { 258 | position: absolute !important; 259 | top: 0 !important; 260 | right: 0 !important; 261 | bottom: 0 !important; 262 | background: black !important; 263 | opacity: 0 !important; 264 | width: 3px !important; 265 | cursor: col-resize !important; 266 | } 267 | 268 | .super_links_table-resize-handle:hover, 269 | /* The following selector is needed so the handle is visible during resize even if the mouse isn't over the handle anymore */ 270 | .super_links_table-header--being-resized .super_links_table-resize-handle { 271 | opacity: 0.5 !important; 272 | } 273 | 274 | .super_links_popup-resizer, .super_links_chatgpt-resizer { 275 | width: 10px !important; 276 | height: 10px !important; 277 | position: absolute !important; 278 | right: 1px !important; 279 | bottom: 1px !important; 280 | cursor: se-resize !important; 281 | } 282 | 283 | table.super_links_table th:hover .super_links_table-resize-handle { 284 | opacity: 0.3 !important; 285 | } 286 | 287 | table.super_links_table td { 288 | padding-top: 10px !important; 289 | padding-bottom: 10px !important; 290 | color: #808080 !important; 291 | } 292 | 293 | table.super_links_table tr:nth-child(even) td { 294 | background: #f8f6ff !important; 295 | } 296 | 297 | -------------------------------------------------------------------------------- /src/dataview.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenLink Structured Data Sniffer 3 | * 4 | * Copyright (C) 2015-2021 OpenLink Software 5 | * 6 | * This project is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License as published by the 8 | * Free Software Foundation; only version 2 of the License, dated June 1991. 9 | * 10 | * This program is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, write to the Free Software Foundation, Inc., 17 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | .hidden { 22 | display: none !important; 23 | } 24 | 25 | .super_links_msg { 26 | all: initial; 27 | display: none; 28 | line-height: normal !important; 29 | flex-direction: row !important; 30 | position: fixed !important; 31 | border: 2px solid #000 !important; 32 | border-radius: 2px !important; 33 | width: 200px !important; 34 | height: 20px !important; 35 | top:4px !important; 36 | left: 4px !important; 37 | background: khaki !important; 38 | color: black !important; 39 | z-index: 2147483647 !important; 40 | padding: 10px 10px 10px 20px !important; 41 | font-family: Arial, Helvetica, sans-serif !important; 42 | font-size: 14px !important; 43 | box-sizing: content-box !important; 44 | } 45 | 46 | .super_links_img { 47 | width: 16px !important; 48 | height: 16px !important; 49 | } 50 | 51 | #super_links_snackbar { 52 | visibility: hidden; 53 | min-width: 250px !important; 54 | margin-left: -125px !important; 55 | background-color: #333 !important; 56 | color: #fff !important; 57 | text-align: center !important; 58 | border-radius: 2px !important; 59 | padding: 16px !important; 60 | position: fixed !important; 61 | z-index: 1 !important; 62 | left: 50% !important; 63 | bottom: 30px !important; 64 | font-size: 17px !important; 65 | } 66 | 67 | #super_links_snackbar.show { 68 | visibility: visible; 69 | -webkit-animation: fadein 0.5s, fadeout 0.5s 2.5s !important; 70 | animation: fadein 0.5s, fadeout 0.5s 2.5s !important; 71 | } 72 | 73 | 74 | .super_links_msg { 75 | display: none; 76 | position: fixed; 77 | border: 2px solid #000; 78 | border-radius: 2px; 79 | width: 200px; 80 | height: 20px; 81 | top:50px; 82 | left: 200px; 83 | background: khaki; 84 | color: black; 85 | z-index: 2147483647; 86 | padding: 5px 10px 10px 20px; 87 | font-family: Arial, Helvetica, sans-serif; 88 | } 89 | 90 | 91 | .super_links_img { 92 | width: 16px; 93 | height: 16px; 94 | } 95 | 96 | 97 | input[type="image"] { 98 | outline: none !important; 99 | } 100 | 101 | #docdata_view{ 102 | } 103 | 104 | table.wait { 105 | font-size: 12px; 106 | } 107 | 108 | table.docdata { 109 | border: 1px solid #000; 110 | width:100%; 111 | table-layout: fixed; 112 | font-size: 12px; 113 | word-wrap:break-word; 114 | } 115 | 116 | 117 | table.docdata > tbody { 118 | border: none; 119 | } 120 | table.docdata td { 121 | vertical-align: top; 122 | color: #000; 123 | } 124 | table.docdata > tbody > tr > td:first-child { 125 | min-width: 200px; 126 | width: 200px; 127 | } 128 | table.docdata > tbody > tr > td:first-child { 129 | padding-left: 20px; 130 | } 131 | table.docdata > tbody > tr.major > td:first-child { 132 | font-weight: bold; 133 | padding-left: 10px; 134 | } 135 | table.docdata > tbody > tr > td.major { 136 | font-weight: bold; 137 | } 138 | 139 | table.docdata > tbody > tr > td.typeid { 140 | font-weight: bold; 141 | /* background-color: #f1f0ee;*/ 142 | } 143 | 144 | 145 | 146 | div#header { 147 | height: 15px; 148 | } 149 | 150 | 151 | .top { 152 | width: 100%; 153 | height: 5px; 154 | } 155 | 156 | 157 | .btn_block { 158 | position: absolute; 159 | right: 10px; 160 | top: 8px; 161 | display:flex; 162 | flex-direction:row; 163 | } 164 | .action_btn { 165 | width: 30px; 166 | height: 24px; 167 | } 168 | .image_btn { 169 | width: 24px; 170 | height: 24px; 171 | padding: 0 4; 172 | } 173 | 174 | 175 | .bottom_block { 176 | position: absolute; 177 | display: flex; 178 | flex-direction: row; 179 | align-items: flex-end; 180 | justify-content: space-between; 181 | flex-shrink: 0; 182 | bottom: 5px; 183 | height: 20px; 184 | width: 95vw; 185 | color: gray; 186 | font-size: 10px; 187 | } 188 | 189 | .bottom_block_left { 190 | display: flex; 191 | align-items: left; 192 | } 193 | 194 | .popup { font-size: 14px; } 195 | 196 | .popup_flex_cols { 197 | style="display:flex; 198 | flex-direction:column" 199 | } 200 | 201 | .popup_frm_row { 202 | display:flex; 203 | padding-bottom: 5px; 204 | align-items: center; 205 | } 206 | 207 | .popup_frm_label4 { 208 | width: 4.5em; 209 | text-align: end; 210 | padding-right: 5px; 211 | } 212 | 213 | .popup_frm_label6 { 214 | width: 6.5em; 215 | text-align: end; 216 | padding-right: 5px; 217 | } 218 | 219 | 220 | .rest_path { 221 | display:flex; 222 | flex-direction:row; 223 | align-items:center; 224 | background-color: #dce9f9; 225 | font-weight: bold; 226 | border: 1px solid #000; 227 | border-radius: 6px; 228 | border-color: lightgray; 229 | } 230 | 231 | .rest_frm_label5 { 232 | margin:5px; 233 | margin-right:5px; 234 | width:5em; 235 | text-align:end; 236 | } 237 | 238 | .rest_frm_label9 { 239 | margin:5px; 240 | margin-right:5px; 241 | width:9em; 242 | text-align:end; 243 | } 244 | 245 | .rest_frm_field { 246 | margin-right:3px; 247 | width:100%; 248 | } 249 | 250 | 251 | .rest_query_title { 252 | display:flex; 253 | flex-direction:row; 254 | align-items:baseline; 255 | background-color: #dce9f9; 256 | font-weight: bold; 257 | } -------------------------------------------------------------------------------- /src/frame_scan.js: -------------------------------------------------------------------------------- 1 | function frame_getSelectionString(el, win) 2 | { 3 | win = win || window; 4 | var doc = win.document, sel, range, prevRange, selString; 5 | 6 | if (win.getSelection && doc.createRange) { 7 | sel = win.getSelection(); 8 | if (sel && sel.rangeCount) { 9 | prevRange = sel.getRangeAt(0); 10 | } 11 | range = doc.createRange(); 12 | range.selectNodeContents(el); 13 | sel.removeAllRanges(); 14 | sel.addRange(range); 15 | selString = sel.toString(); 16 | sel.removeAllRanges(); 17 | prevRange && sel.addRange(prevRange); 18 | } 19 | else if (doc.body.createTextRange) { 20 | range = doc.body.createTextRange(); 21 | range.moveToElementText(el); 22 | range.select(); 23 | } 24 | return selString; 25 | } 26 | 27 | function getContent() 28 | { 29 | let lst = []; 30 | for(const v of document.body.childNodes) { 31 | if (v.nodeName !== 'SCRIPT' 32 | && v.nodeName !== 'STYLE' 33 | && v.nodeName !== 'NOSCRIPT' 34 | && v.nodeName !== 'IFRAME') 35 | { 36 | lst.push(v.innerText); 37 | } 38 | } 39 | return lst.join(''); 40 | } 41 | 42 | function scan_dom() 43 | { 44 | let page_content = getContent(); // document.body.innerText; 45 | 46 | if (!page_content|| (page_content && page_content.length == 0)) 47 | page_content = frame_getSelectionString(document.body); 48 | 49 | page_content = cleanText(page_content); 50 | 51 | try { 52 | let ancs = {} 53 | for(const v of document.querySelectorAll('a')) 54 | if (v.href) 55 | ancs[v.textContent] = v.href 56 | 57 | let links = []; 58 | for(const text of Object.keys(ancs)) 59 | { 60 | if (text) { 61 | const name = this.cleanText(text); 62 | const text_href = ancs[text]; 63 | 64 | if (name.length < 3 || text.length < 3) { 65 | links.push({name, href:text_href}); 66 | continue; 67 | } 68 | 69 | if (page_content.indexOf(text)!==-1) { 70 | page_content = page_content.replaceAll(text, `[${name}](${text_href})`); 71 | } 72 | else if (name && page_content.indexOf(name)!==-1) { 73 | page_content = page_content.replaceAll(name, `[${name}](${text_href})`); 74 | } 75 | else if (name && text_href) 76 | links.push({name, href:text_href}); 77 | } 78 | } 79 | 80 | let page_add = []; 81 | page_add.push('Links:'); 82 | for(const v of links) { 83 | const name = cleanText(v.name); 84 | if (!v.href || !name) 85 | continue; 86 | page_add.push(` [${name}](${v.href})`); 87 | } 88 | 89 | let images = {}; 90 | for(const v of document.querySelectorAll('img')) 91 | if (!v.src.endsWith('.svg') && v.src.startsWith('https:')) 92 | images[v.src]=1; 93 | 94 | for(const v of document.querySelectorAll('video')) 95 | if (v.src.startsWith('https:')) 96 | images[v.src]=2; 97 | 98 | for(const v of Object.keys(images)) 99 | { 100 | if (images[v] === 2) 101 | page_add.push(` ![Video](${v})`); 102 | else 103 | page_add.push(` ![Image](${v})`); 104 | } 105 | 106 | return page_content+'\n'+page_add.join('\n'); 107 | } catch(e) { 108 | console.log(e); 109 | return page_content; 110 | } 111 | } 112 | 113 | 114 | function cleanText(text) 115 | { 116 | if (!text) 117 | return text; 118 | 119 | return text.trim() 120 | .replace(/(\n){4,}/g, "\n\n\n") 121 | // .replace(/\n\n/g, " ") 122 | .replace(/ {3,}/g, " ") 123 | .replace(/\t/g, "") 124 | .replace(/\n+(\s*\n)*/g, "\n") 125 | } 126 | 127 | scan_dom(); 128 | -------------------------------------------------------------------------------- /src/frame_text.js: -------------------------------------------------------------------------------- 1 | function frame_getSelectionString(el, win) 2 | { 3 | win = win || window; 4 | var doc = win.document, sel, range, prevRange, selString; 5 | 6 | if (win.getSelection && doc.createRange) { 7 | sel = win.getSelection(); 8 | if (sel && sel.rangeCount) { 9 | prevRange = sel.getRangeAt(0); 10 | } 11 | range = doc.createRange(); 12 | range.selectNodeContents(el); 13 | sel.removeAllRanges(); 14 | sel.addRange(range); 15 | selString = sel.toString(); 16 | sel.removeAllRanges(); 17 | prevRange && sel.addRange(prevRange); 18 | } 19 | else if (doc.body.createTextRange) { 20 | range = doc.body.createTextRange(); 21 | range.moveToElementText(el); 22 | range.select(); 23 | } 24 | return selString; 25 | } 26 | 27 | 28 | function getContent() 29 | { 30 | let lst = []; 31 | for(const v of document.body.childNodes) { 32 | if (v.nodeName !== 'SCRIPT' 33 | && v.nodeName !== 'STYLE' 34 | && v.nodeName !== 'NOSCRIPT' 35 | && v.nodeName !== 'IFRAME') 36 | lst.push(v.innerText); 37 | } 38 | return lst.join(''); 39 | } 40 | 41 | function frame_text() 42 | { 43 | var txt = document.body ? getContent() : null; 44 | 45 | if (txt === undefined || (txt!==null && txt.length==0)) 46 | txt = frame_getSelectionString(document.body); 47 | 48 | return txt? txt : " "; 49 | } 50 | 51 | 52 | frame_text(); 53 | -------------------------------------------------------------------------------- /src/helpers_ui.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenLink Structured Data Sniffer 3 | * 4 | * Copyright (C) 2015-2021 OpenLink Software 5 | * 6 | * This project is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License as published by the 8 | * Free Software Foundation; only version 2 of the License, dated June 1991. 9 | * 10 | * This program is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, write to the Free Software Foundation, Inc., 17 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | 22 | function makeResizableTable(tableId, columns_css, containerId) { 23 | var table = DOM.qSel(tableId); 24 | var popup = DOM.qSel(containerId); 25 | var headerResized; 26 | const columns = []; 27 | 28 | table.style.gridTemplateColumns = columns_css.join(' '); 29 | 30 | function onMouseMove(e) 31 | { 32 | window.requestAnimationFrame(() => { 33 | // Calculate the desired width 34 | if (headerResized===null) 35 | return; 36 | 37 | var horizontalScrollOffset = document.documentElement.scrollLeft; 38 | const width = (horizontalScrollOffset + e.clientX) - popup.offsetLeft - headerResized.offsetLeft; 39 | 40 | // Update the column object with the new size value 41 | const column = columns.find(({ header }) => header === headerResized); 42 | column.size = Math.max(100, width) + 'px'; // Enforce our minimum 43 | 44 | // For the other headers which don't have a set width, fix it to their computed width 45 | columns.forEach((column) => { 46 | if(column.size.startsWith('minmax')){ // isn't fixed yet (it would be a pixel value otherwise) 47 | column.size = parseInt(column.header.clientWidth, 10) + 'px'; 48 | } 49 | }) 50 | 51 | // Update the column sizes 52 | // Reminder: grid-template-columns sets the width for all columns in one value 53 | table.style.gridTemplateColumns = columns 54 | .map(({ header, size }) => size) 55 | .join(' '); 56 | }); 57 | } 58 | 59 | function onMouseUp(e) 60 | { 61 | if (headerResized) 62 | headerResized.classList.remove('super_links_table-header--being-resized'); 63 | 64 | window.removeEventListener('mousemove', onMouseMove); 65 | window.removeEventListener('mouseup', onMouseUp); 66 | headerResized.classList.remove('super_links_table-header--being-resized'); 67 | headerResized = null; 68 | } 69 | 70 | 71 | var lst = DOM.qSelAll(tableId+' th'); 72 | var i = 0; 73 | 74 | for(const header of lst) 75 | { 76 | columns.push({ 77 | header, 78 | size: columns_css[i], 79 | }); 80 | 81 | header.querySelector('.super_links_table-resize-handle').onmousedown = (e) => { 82 | headerResized = e.target.parentNode; 83 | window.addEventListener('mousemove', onMouseMove); 84 | window.addEventListener('mouseup', onMouseUp); 85 | headerResized.classList.add('super_links_table-header--being-resized'); 86 | } 87 | } 88 | } 89 | 90 | 91 | function dragElement(el, elHeader) { 92 | var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; 93 | var vpH = 0, vpW = 0; 94 | 95 | 96 | if (elHeader) { 97 | // if present, the header is where you move the DIV from: 98 | elHeader.onmousedown = onMouseDown; 99 | } else { 100 | // otherwise, move the DIV from anywhere inside the DIV: 101 | el.onmousedown = onMouseDown; 102 | } 103 | 104 | function onMouseDown(e) { 105 | e = e || window.event; 106 | e.preventDefault(); 107 | // get the mouse cursor position at startup: 108 | pos3 = e.clientX; 109 | pos4 = e.clientY; 110 | 111 | vpWH = getViewPortWidthHeight(); 112 | vpW = vpWH[0]; 113 | vpH = vpWH[1]; 114 | 115 | window.addEventListener('mousemove', onMouseMove); 116 | window.addEventListener('mouseup', onMouseUp); 117 | } 118 | 119 | function onMouseMove(e) { 120 | e = e || window.event; 121 | e.preventDefault(); 122 | // calculate the new cursor position: 123 | pos1 = pos3 - e.clientX; 124 | pos2 = pos4 - e.clientY; 125 | pos3 = e.clientX; 126 | pos4 = e.clientY; 127 | // set the element's new position: 128 | var top = (el.offsetTop - pos2); 129 | var left = (el.offsetLeft - pos1); 130 | 131 | top = top<0? 0: top; 132 | top = top>vpH-20? vpH-20: top; 133 | left = left<0? 0: left; 134 | left = left>vpW-30? vpW-30: left; 135 | 136 | el.style.top = top + "px"; 137 | el.style.left = left + "px"; 138 | } 139 | 140 | function onMouseUp() { 141 | // stop moving when mouse button is released: 142 | window.removeEventListener('mousemove', onMouseMove); 143 | window.removeEventListener('mouseup', onMouseUp); 144 | } 145 | } 146 | 147 | function makeResizable(el, elResizer) 148 | { 149 | var orig_height = 0; 150 | var orig_width = 0; 151 | var orig_mouse_x = 0; 152 | var orig_mouse_y = 0; 153 | 154 | elResizer.onmousedown = (e) => { 155 | e.preventDefault(); 156 | orig_width = parseFloat(getComputedStyle(el, null).getPropertyValue('width').replace('px', '')); 157 | orig_height = parseFloat(getComputedStyle(el, null).getPropertyValue('height').replace('px', '')); 158 | orig_mouse_x = e.pageX; 159 | orig_mouse_y = e.pageY; 160 | 161 | window.addEventListener('mousemove', onMouseMove); 162 | window.addEventListener('mouseup', onMouseUp); 163 | } 164 | 165 | function onMouseMove(e) { 166 | el.style.width = Math.max(orig_width + (e.pageX - orig_mouse_x), 600) + 'px'; 167 | el.style.height = Math.max(orig_height + (e.pageY - orig_mouse_y), 150) + 'px'; 168 | } 169 | 170 | function onMouseUp() { 171 | window.removeEventListener('mousemove', onMouseMove); 172 | window.removeEventListener('mouseup', onMouseUp); 173 | } 174 | } 175 | 176 | function positionPopupOnPage(popupId, evt ) 177 | { 178 | var vpWH = []; 179 | var vpW, vpH; 180 | var intCoordX = evt.clientX; 181 | var intCoordY = evt.clientY; 182 | var intXOffset = intCoordX; 183 | var intYOffset = intCoordY; 184 | 185 | vpWH = getViewPortWidthHeight(); 186 | vpW = vpWH[0]; 187 | vpH = vpWH[1]; 188 | 189 | var popup = $(popupId); 190 | popup.css("position","fixed"); 191 | // if not display: block, .offsetWidth & .offsetHeight === 0 192 | popup.css("display","block"); 193 | popup.css("zIndex","2147483647"); 194 | 195 | if ( intCoordX > vpW/2 ) 196 | intXOffset -= popup.width(); 197 | 198 | if ( intCoordY > vpH/2 ) 199 | intYOffset -= popup.height(); 200 | 201 | if ( vpW <= 500 ) 202 | intXOffset = ( vpW - popup.width() ) / 2; 203 | 204 | if ( vpH <= 500 ) 205 | intYOffset = (vpH - popup.height() ) / 2; 206 | 207 | var rpos = intXOffset + popup.outerWidth() + 5; 208 | if (rpos > vpW) 209 | intXOffset -= rpos - vpW; 210 | 211 | if (intXOffset < 0 ) 212 | intXOffset = 2; 213 | 214 | if (intYOffset < 0 ) 215 | intYOffset = 2; 216 | 217 | popup.css("top", intYOffset + 'px'); 218 | popup.css("left", intXOffset + 'px'); 219 | popup.css("visibility", 'visible'); 220 | } 221 | 222 | 223 | function getViewPortWidthHeight() 224 | { 225 | var viewPortWidth; 226 | var viewPortHeight; 227 | 228 | // the more standards compliant browsers (mozilla/netscape/opera/IE7) 229 | // use window.innerWidth and window.innerHeight 230 | if (typeof window.innerWidth != 'undefined') 231 | { 232 | viewPortWidth = window.innerWidth; 233 | viewPortHeight = window.innerHeight; 234 | } 235 | 236 | return [viewPortWidth, viewPortHeight]; 237 | } 238 | 239 | -------------------------------------------------------------------------------- /src/images/chat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/images/chat.png -------------------------------------------------------------------------------- /src/images/copy-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/images/icon128.png -------------------------------------------------------------------------------- /src/images/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/images/icon16.png -------------------------------------------------------------------------------- /src/images/icon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/images/icon48.png -------------------------------------------------------------------------------- /src/images/message.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/images/osds-icon-annotate-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/images/osds-icon-annotate-24.png -------------------------------------------------------------------------------- /src/images/osds-icon-describe-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/images/osds-icon-describe-24.png -------------------------------------------------------------------------------- /src/images/osds-icon-download-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/images/osds-icon-download-24.png -------------------------------------------------------------------------------- /src/images/osds-icon-query-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/images/osds-icon-query-24.png -------------------------------------------------------------------------------- /src/images/osds-icon-rest-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/images/osds-icon-rest-24.png -------------------------------------------------------------------------------- /src/images/osds-icon-settings-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/images/osds-icon-settings-24.png -------------------------------------------------------------------------------- /src/images/osds-icon-upload-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/images/osds-icon-upload-24.png -------------------------------------------------------------------------------- /src/images/person-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/images/plus.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/robot.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 23 | 24 | 25 | 26 | 27 | 31 | 32 | 33 | 34 | 35 | 38 | 39 | 40 | 41 | 42 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /src/images/slink24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/images/slink24.png -------------------------------------------------------------------------------- /src/images/slogin24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/images/slogin24.png -------------------------------------------------------------------------------- /src/images/throbber.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/images/throbber.gif -------------------------------------------------------------------------------- /src/images/thumb-down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/images/thumb-down.png -------------------------------------------------------------------------------- /src/images/thumb-up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/images/thumb-up.png -------------------------------------------------------------------------------- /src/images/uid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/images/uid.png -------------------------------------------------------------------------------- /src/lib/FileSaver.js: -------------------------------------------------------------------------------- 1 | /* FileSaver.js 2 | * A saveAs() FileSaver implementation. 3 | * 1.1.20151003 4 | * 5 | * By Eli Grey, http://eligrey.com 6 | * License: MIT 7 | * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md 8 | */ 9 | 10 | /*global self */ 11 | /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */ 12 | 13 | /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ 14 | 15 | var saveAs = saveAs || (function(view) { 16 | "use strict"; 17 | // IE <10 is explicitly unsupported 18 | if (typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) { 19 | return; 20 | } 21 | var 22 | doc = view.document 23 | // only get URL when necessary in case Blob.js hasn't overridden it yet 24 | , get_URL = function() { 25 | return view.URL || view.webkitURL || view; 26 | } 27 | , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a") 28 | , can_use_save_link = "download" in save_link 29 | , is_safari = /Version\/[\d\.]+.*Safari/.test(navigator.userAgent) 30 | , click = function(node) { 31 | if (is_safari) { 32 | doc.body.appendChild(node); 33 | node.click(); 34 | } 35 | else { 36 | var event = new MouseEvent("click"); 37 | node.dispatchEvent(event); 38 | } 39 | } 40 | , webkit_req_fs = view.webkitRequestFileSystem 41 | , req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem 42 | , throw_outside = function(ex) { 43 | (view.setImmediate || view.setTimeout)(function() { 44 | throw ex; 45 | }, 0); 46 | } 47 | , force_saveable_type = "application/octet-stream" 48 | , fs_min_size = 0 49 | // See https://code.google.com/p/chromium/issues/detail?id=375297#c7 and 50 | // https://github.com/eligrey/FileSaver.js/commit/485930a#commitcomment-8768047 51 | // for the reasoning behind the timeout and revocation flow 52 | , arbitrary_revoke_timeout = 2000 // in ms 53 | , revoke = function(file) { 54 | var revoker = function() { 55 | if (typeof file === "string") { // file is an object URL 56 | get_URL().revokeObjectURL(file); 57 | } else { // file is a File 58 | file.remove(); 59 | } 60 | if (is_safari) 61 | doc.body.removeChild(save_link); 62 | }; 63 | 64 | if (view.chrome && !is_safari) { 65 | revoker(); 66 | } else { 67 | setTimeout(revoker, arbitrary_revoke_timeout); 68 | } 69 | } 70 | , dispatch = function(filesaver, event_types, event) { 71 | event_types = [].concat(event_types); 72 | var i = event_types.length; 73 | while (i--) { 74 | var listener = filesaver["on" + event_types[i]]; 75 | if (typeof listener === "function") { 76 | try { 77 | listener.call(filesaver, event || filesaver); 78 | } catch (ex) { 79 | throw_outside(ex); 80 | } 81 | } 82 | } 83 | } 84 | , auto_bom = function(blob) { 85 | // prepend BOM for UTF-8 XML and text/* types (including HTML) 86 | if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) { 87 | return new Blob(["\ufeff", blob], {type: blob.type}); 88 | } 89 | return blob; 90 | } 91 | , FileSaver = function(blob, name, no_auto_bom) { 92 | if (!no_auto_bom) { 93 | blob = auto_bom(blob); 94 | } 95 | // First try a.download, then web filesystem, then object URLs 96 | var 97 | filesaver = this 98 | , type = blob.type 99 | , blob_changed = false 100 | , object_url 101 | , target_view 102 | , dispatch_all = function() { 103 | dispatch(filesaver, "writestart progress write writeend".split(" ")); 104 | } 105 | // on any filesys errors revert to saving with object URLs 106 | , fs_error = function() { 107 | if (target_view && is_safari && typeof FileReader !== "undefined") { 108 | // Safari doesn't allow downloading of blob urls 109 | var reader = new FileReader(); 110 | reader.onloadend = function() { 111 | var base64Data = reader.result; 112 | target_view.location.href = "data:attachment/file" + base64Data.slice(base64Data.search(/[,;]/)); 113 | filesaver.readyState = filesaver.DONE; 114 | dispatch_all(); 115 | }; 116 | reader.readAsDataURL(blob); 117 | filesaver.readyState = filesaver.INIT; 118 | return; 119 | } 120 | // don't create more object URLs than needed 121 | if (blob_changed || !object_url) { 122 | object_url = get_URL().createObjectURL(blob); 123 | } 124 | if (target_view) { 125 | target_view.location.href = object_url; 126 | } else { 127 | var new_tab = view.open(object_url, "_blank"); 128 | if (new_tab == undefined && is_safari) { 129 | //Apple do not allow window.open, see http://bit.ly/1kZffRI 130 | view.location.href = object_url 131 | } 132 | } 133 | filesaver.readyState = filesaver.DONE; 134 | dispatch_all(); 135 | revoke(object_url); 136 | } 137 | , abortable = function(func) { 138 | return function() { 139 | if (filesaver.readyState !== filesaver.DONE) { 140 | return func.apply(this, arguments); 141 | } 142 | }; 143 | } 144 | , create_if_not_found = {create: true, exclusive: false} 145 | , slice 146 | ; 147 | filesaver.readyState = filesaver.INIT; 148 | if (!name) { 149 | name = "download"; 150 | } 151 | if (can_use_save_link) { 152 | object_url = get_URL().createObjectURL(blob); 153 | setTimeout(function() { 154 | save_link.href = object_url; 155 | save_link.download = name; 156 | click(save_link); 157 | dispatch_all(); 158 | revoke(object_url); 159 | filesaver.readyState = filesaver.DONE; 160 | }); 161 | return; 162 | } 163 | // Object and web filesystem URLs have a problem saving in Google Chrome when 164 | // viewed in a tab, so I force save with application/octet-stream 165 | // http://code.google.com/p/chromium/issues/detail?id=91158 166 | // Update: Google errantly closed 91158, I submitted it again: 167 | // https://code.google.com/p/chromium/issues/detail?id=389642 168 | if (view.chrome && type && type !== force_saveable_type) { 169 | slice = blob.slice || blob.webkitSlice; 170 | blob = slice.call(blob, 0, blob.size, force_saveable_type); 171 | blob_changed = true; 172 | } 173 | // Since I can't be sure that the guessed media type will trigger a download 174 | // in WebKit, I append .download to the filename. 175 | // https://bugs.webkit.org/show_bug.cgi?id=65440 176 | if (webkit_req_fs && name !== "download") { 177 | name += ".download"; 178 | } 179 | if (type === force_saveable_type || webkit_req_fs) { 180 | target_view = view; 181 | } 182 | if (!req_fs) { 183 | fs_error(); 184 | return; 185 | } 186 | fs_min_size += blob.size; 187 | req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) { 188 | fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) { 189 | var save = function() { 190 | dir.getFile(name, create_if_not_found, abortable(function(file) { 191 | file.createWriter(abortable(function(writer) { 192 | writer.onwriteend = function(event) { 193 | target_view.location.href = file.toURL(); 194 | filesaver.readyState = filesaver.DONE; 195 | dispatch(filesaver, "writeend", event); 196 | revoke(file); 197 | }; 198 | writer.onerror = function() { 199 | var error = writer.error; 200 | if (error.code !== error.ABORT_ERR) { 201 | fs_error(); 202 | } 203 | }; 204 | "writestart progress write abort".split(" ").forEach(function(event) { 205 | writer["on" + event] = filesaver["on" + event]; 206 | }); 207 | writer.write(blob); 208 | filesaver.abort = function() { 209 | writer.abort(); 210 | filesaver.readyState = filesaver.DONE; 211 | }; 212 | filesaver.readyState = filesaver.WRITING; 213 | }), fs_error); 214 | }), fs_error); 215 | }; 216 | dir.getFile(name, {create: false}, abortable(function(file) { 217 | // delete file if it already exists 218 | file.remove(); 219 | save(); 220 | }), abortable(function(ex) { 221 | if (ex.code === ex.NOT_FOUND_ERR) { 222 | save(); 223 | } else { 224 | fs_error(); 225 | } 226 | })); 227 | }), fs_error); 228 | }), fs_error); 229 | } 230 | , FS_proto = FileSaver.prototype 231 | , saveAs = function(blob, name, no_auto_bom) { 232 | return new FileSaver(blob, name, no_auto_bom); 233 | } 234 | ; 235 | // IE 10+ (native saveAs) 236 | if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) { 237 | return function(blob, name, no_auto_bom) { 238 | if (!no_auto_bom) { 239 | blob = auto_bom(blob); 240 | } 241 | return navigator.msSaveOrOpenBlob(blob, name || "download"); 242 | }; 243 | } 244 | 245 | FS_proto.abort = function() { 246 | var filesaver = this; 247 | filesaver.readyState = filesaver.DONE; 248 | dispatch(filesaver, "abort"); 249 | }; 250 | FS_proto.readyState = FS_proto.INIT = 0; 251 | FS_proto.WRITING = 1; 252 | FS_proto.DONE = 2; 253 | 254 | FS_proto.error = 255 | FS_proto.onwritestart = 256 | FS_proto.onprogress = 257 | FS_proto.onwrite = 258 | FS_proto.onabort = 259 | FS_proto.onerror = 260 | FS_proto.onwriteend = 261 | null; 262 | 263 | return saveAs; 264 | }( 265 | typeof window !== "undefined" && window 266 | || this.content 267 | )); 268 | // `self` is undefined in Firefox for Android content script context 269 | // while `this` is nsIContentFrameMessageManager 270 | // with an attribute `content` that corresponds to the window 271 | 272 | if (typeof module !== "undefined" && module.exports) { 273 | module.exports.saveAs = saveAs; 274 | } else if ((typeof define !== "undefined" && define !== null) && (define.amd != null)) { 275 | define([], function() { 276 | return saveAs; 277 | }); 278 | } 279 | -------------------------------------------------------------------------------- /src/lib/css/codemirror.css: -------------------------------------------------------------------------------- 1 | /* BASICS */ 2 | 3 | .CodeMirror { 4 | /* Set height, width, borders, and global font properties here */ 5 | font-family: monospace; 6 | height: 300px; 7 | color: black; 8 | direction: ltr; 9 | } 10 | 11 | /* PADDING */ 12 | 13 | .CodeMirror-lines { 14 | padding: 4px 0; /* Vertical padding around content */ 15 | } 16 | .CodeMirror pre.CodeMirror-line, 17 | .CodeMirror pre.CodeMirror-line-like { 18 | padding: 0 4px; /* Horizontal padding of content */ 19 | } 20 | 21 | .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { 22 | background-color: white; /* The little square between H and V scrollbars */ 23 | } 24 | 25 | /* GUTTER */ 26 | 27 | .CodeMirror-gutters { 28 | border-right: 1px solid #ddd; 29 | background-color: #f7f7f7; 30 | white-space: nowrap; 31 | } 32 | .CodeMirror-linenumbers {} 33 | .CodeMirror-linenumber { 34 | padding: 0 3px 0 5px; 35 | min-width: 20px; 36 | text-align: right; 37 | color: #999; 38 | white-space: nowrap; 39 | } 40 | 41 | .CodeMirror-guttermarker { color: black; } 42 | .CodeMirror-guttermarker-subtle { color: #999; } 43 | 44 | /* CURSOR */ 45 | 46 | .CodeMirror-cursor { 47 | border-left: 1px solid black; 48 | border-right: none; 49 | width: 0; 50 | } 51 | /* Shown when moving in bi-directional text */ 52 | .CodeMirror div.CodeMirror-secondarycursor { 53 | border-left: 1px solid silver; 54 | } 55 | .cm-fat-cursor .CodeMirror-cursor { 56 | width: auto; 57 | border: 0 !important; 58 | background: #7e7; 59 | } 60 | .cm-fat-cursor div.CodeMirror-cursors { 61 | z-index: 1; 62 | } 63 | .cm-fat-cursor .CodeMirror-line::selection, 64 | .cm-fat-cursor .CodeMirror-line > span::selection, 65 | .cm-fat-cursor .CodeMirror-line > span > span::selection { background: transparent; } 66 | .cm-fat-cursor .CodeMirror-line::-moz-selection, 67 | .cm-fat-cursor .CodeMirror-line > span::-moz-selection, 68 | .cm-fat-cursor .CodeMirror-line > span > span::-moz-selection { background: transparent; } 69 | .cm-fat-cursor { caret-color: transparent; } 70 | @-moz-keyframes blink { 71 | 0% {} 72 | 50% { background-color: transparent; } 73 | 100% {} 74 | } 75 | @-webkit-keyframes blink { 76 | 0% {} 77 | 50% { background-color: transparent; } 78 | 100% {} 79 | } 80 | @keyframes blink { 81 | 0% {} 82 | 50% { background-color: transparent; } 83 | 100% {} 84 | } 85 | 86 | /* Can style cursor different in overwrite (non-insert) mode */ 87 | .CodeMirror-overwrite .CodeMirror-cursor {} 88 | 89 | .cm-tab { display: inline-block; text-decoration: inherit; } 90 | 91 | .CodeMirror-rulers { 92 | position: absolute; 93 | left: 0; right: 0; top: -50px; bottom: 0; 94 | overflow: hidden; 95 | } 96 | .CodeMirror-ruler { 97 | border-left: 1px solid #ccc; 98 | top: 0; bottom: 0; 99 | position: absolute; 100 | } 101 | 102 | /* DEFAULT THEME */ 103 | 104 | .cm-s-default .cm-header {color: blue;} 105 | .cm-s-default .cm-quote {color: #090;} 106 | .cm-negative {color: #d44;} 107 | .cm-positive {color: #292;} 108 | .cm-header, .cm-strong {font-weight: bold;} 109 | .cm-em {font-style: italic;} 110 | .cm-link {text-decoration: underline;} 111 | .cm-strikethrough {text-decoration: line-through;} 112 | 113 | .cm-s-default .cm-keyword {color: #708;} 114 | .cm-s-default .cm-atom {color: #219;} 115 | .cm-s-default .cm-number {color: #164;} 116 | .cm-s-default .cm-def {color: #00f;} 117 | .cm-s-default .cm-variable, 118 | .cm-s-default .cm-punctuation, 119 | .cm-s-default .cm-property, 120 | .cm-s-default .cm-operator {} 121 | .cm-s-default .cm-variable-2 {color: #05a;} 122 | .cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;} 123 | .cm-s-default .cm-comment {color: #a50;} 124 | .cm-s-default .cm-string {color: #a11;} 125 | .cm-s-default .cm-string-2 {color: #f50;} 126 | .cm-s-default .cm-meta {color: #555;} 127 | .cm-s-default .cm-qualifier {color: #555;} 128 | .cm-s-default .cm-builtin {color: #30a;} 129 | .cm-s-default .cm-bracket {color: #997;} 130 | .cm-s-default .cm-tag {color: #170;} 131 | .cm-s-default .cm-attribute {color: #00c;} 132 | .cm-s-default .cm-hr {color: #999;} 133 | .cm-s-default .cm-link {color: #00c;} 134 | 135 | .cm-s-default .cm-error {color: #f00;} 136 | .cm-invalidchar {color: #f00;} 137 | 138 | .CodeMirror-composing { border-bottom: 2px solid; } 139 | 140 | /* Default styles for common addons */ 141 | 142 | div.CodeMirror span.CodeMirror-matchingbracket {color: #0b0;} 143 | div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;} 144 | .CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } 145 | .CodeMirror-activeline-background {background: #e8f2ff;} 146 | 147 | /* STOP */ 148 | 149 | /* The rest of this file contains styles related to the mechanics of 150 | the editor. You probably shouldn't touch them. */ 151 | 152 | .CodeMirror { 153 | position: relative; 154 | overflow: hidden; 155 | background: white; 156 | } 157 | 158 | .CodeMirror-scroll { 159 | overflow: scroll !important; /* Things will break if this is overridden */ 160 | /* 50px is the magic margin used to hide the element's real scrollbars */ 161 | /* See overflow: hidden in .CodeMirror */ 162 | margin-bottom: -50px; margin-right: -50px; 163 | padding-bottom: 50px; 164 | height: 100%; 165 | outline: none; /* Prevent dragging from highlighting the element */ 166 | position: relative; 167 | z-index: 0; 168 | } 169 | .CodeMirror-sizer { 170 | position: relative; 171 | border-right: 50px solid transparent; 172 | } 173 | 174 | /* The fake, visible scrollbars. Used to force redraw during scrolling 175 | before actual scrolling happens, thus preventing shaking and 176 | flickering artifacts. */ 177 | .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { 178 | position: absolute; 179 | z-index: 6; 180 | display: none; 181 | outline: none; 182 | } 183 | .CodeMirror-vscrollbar { 184 | right: 0; top: 0; 185 | overflow-x: hidden; 186 | overflow-y: scroll; 187 | } 188 | .CodeMirror-hscrollbar { 189 | bottom: 0; left: 0; 190 | overflow-y: hidden; 191 | overflow-x: scroll; 192 | } 193 | .CodeMirror-scrollbar-filler { 194 | right: 0; bottom: 0; 195 | } 196 | .CodeMirror-gutter-filler { 197 | left: 0; bottom: 0; 198 | } 199 | 200 | .CodeMirror-gutters { 201 | position: absolute; left: 0; top: 0; 202 | min-height: 100%; 203 | z-index: 3; 204 | } 205 | .CodeMirror-gutter { 206 | white-space: normal; 207 | height: 100%; 208 | display: inline-block; 209 | vertical-align: top; 210 | margin-bottom: -50px; 211 | } 212 | .CodeMirror-gutter-wrapper { 213 | position: absolute; 214 | z-index: 4; 215 | background: none !important; 216 | border: none !important; 217 | } 218 | .CodeMirror-gutter-background { 219 | position: absolute; 220 | top: 0; bottom: 0; 221 | z-index: 4; 222 | } 223 | .CodeMirror-gutter-elt { 224 | position: absolute; 225 | cursor: default; 226 | z-index: 4; 227 | } 228 | .CodeMirror-gutter-wrapper ::selection { background-color: transparent } 229 | .CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent } 230 | 231 | .CodeMirror-lines { 232 | cursor: text; 233 | min-height: 1px; /* prevents collapsing before first draw */ 234 | } 235 | .CodeMirror pre.CodeMirror-line, 236 | .CodeMirror pre.CodeMirror-line-like { 237 | /* Reset some styles that the rest of the page might have set */ 238 | -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; 239 | border-width: 0; 240 | background: transparent; 241 | font-family: inherit; 242 | font-size: inherit; 243 | margin: 0; 244 | white-space: pre; 245 | word-wrap: normal; 246 | line-height: inherit; 247 | color: inherit; 248 | z-index: 2; 249 | position: relative; 250 | overflow: visible; 251 | -webkit-tap-highlight-color: transparent; 252 | -webkit-font-variant-ligatures: contextual; 253 | font-variant-ligatures: contextual; 254 | } 255 | .CodeMirror-wrap pre.CodeMirror-line, 256 | .CodeMirror-wrap pre.CodeMirror-line-like { 257 | word-wrap: break-word; 258 | white-space: pre-wrap; 259 | word-break: normal; 260 | } 261 | 262 | .CodeMirror-linebackground { 263 | position: absolute; 264 | left: 0; right: 0; top: 0; bottom: 0; 265 | z-index: 0; 266 | } 267 | 268 | .CodeMirror-linewidget { 269 | position: relative; 270 | z-index: 2; 271 | padding: 0.1px; /* Force widget margins to stay inside of the container */ 272 | } 273 | 274 | .CodeMirror-widget {} 275 | 276 | .CodeMirror-rtl pre { direction: rtl; } 277 | 278 | .CodeMirror-code { 279 | outline: none; 280 | } 281 | 282 | /* Force content-box sizing for the elements where we expect it */ 283 | .CodeMirror-scroll, 284 | .CodeMirror-sizer, 285 | .CodeMirror-gutter, 286 | .CodeMirror-gutters, 287 | .CodeMirror-linenumber { 288 | -moz-box-sizing: content-box; 289 | box-sizing: content-box; 290 | } 291 | 292 | .CodeMirror-measure { 293 | position: absolute; 294 | width: 100%; 295 | height: 0; 296 | overflow: hidden; 297 | visibility: hidden; 298 | } 299 | 300 | .CodeMirror-cursor { 301 | position: absolute; 302 | pointer-events: none; 303 | } 304 | .CodeMirror-measure pre { position: static; } 305 | 306 | div.CodeMirror-cursors { 307 | visibility: hidden; 308 | position: relative; 309 | z-index: 3; 310 | } 311 | div.CodeMirror-dragcursors { 312 | visibility: visible; 313 | } 314 | 315 | .CodeMirror-focused div.CodeMirror-cursors { 316 | visibility: visible; 317 | } 318 | 319 | .CodeMirror-selected { background: #d9d9d9; } 320 | .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } 321 | .CodeMirror-crosshair { cursor: crosshair; } 322 | .CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; } 323 | .CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; } 324 | 325 | .cm-searching { 326 | background-color: #ffa; 327 | background-color: rgba(255, 255, 0, .4); 328 | } 329 | 330 | /* Used to force a border model for a node */ 331 | .cm-force-border { padding-right: .1px; } 332 | 333 | @media print { 334 | /* Hide the cursor when printing */ 335 | .CodeMirror div.CodeMirror-cursors { 336 | visibility: hidden; 337 | } 338 | } 339 | 340 | /* See issue #2901 */ 341 | .cm-tab-wrap-hack:after { content: ''; } 342 | 343 | /* Help users use markselection to safely style text background */ 344 | span.CodeMirror-selectedtext { background: none; } 345 | -------------------------------------------------------------------------------- /src/lib/css/footable-0.1.css: -------------------------------------------------------------------------------- 1 | .footable { 2 | border-collapse: separate; 3 | border-spacing: 0; 4 | width: 100%; 5 | border: solid #ccc 1px; 6 | -moz-border-radius: 6px; 7 | -webkit-border-radius: 6px; 8 | border-radius: 6px; 9 | font-family: 'trebuchet MS' , 'Lucida sans' , Arial; 10 | font-size: 14px; 11 | color: #444; 12 | } 13 | 14 | .footable.breakpoint > tbody > tr > td.expand { 15 | background: url('img/plus.png') no-repeat 5px center; 16 | padding-left: 40px; 17 | } 18 | 19 | .footable.breakpoint > tbody > tr.footable-detail-show > td.expand { 20 | background: url('img/minus.png') no-repeat 5px center; 21 | } 22 | 23 | .footable.breakpoint > tbody > tr.footable-row-detail { 24 | background: #eee; 25 | } 26 | 27 | .footable > tbody > tr:hover { 28 | background: #fbf8e9; 29 | } 30 | 31 | .footable.breakpoint > tbody > tr:hover:not(.footable-row-detail) { 32 | cursor: pointer; 33 | } 34 | 35 | .footable > tbody > tr > td, .footable > thead > tr > th { 36 | border-left: 1px solid #ccc; 37 | border-top: 1px solid #ccc; 38 | padding: 4px; 39 | text-align: left; 40 | } 41 | 42 | .footable > thead > tr > th, .footable > thead > tr > td { 43 | background-color: #dce9f9; 44 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ebf3fc), to(#dce9f9)); 45 | background-image: -webkit-linear-gradient(top, #ebf3fc, #dce9f9); 46 | background-image: -moz-linear-gradient(top, #ebf3fc, #dce9f9); 47 | background-image: -ms-linear-gradient(top, #ebf3fc, #dce9f9); 48 | background-image: -o-linear-gradient(top, #ebf3fc, #dce9f9); 49 | background-image: linear-gradient(to bottom, #ebf3fc, #dce9f9); 50 | -webkit-box-shadow: 0 1px 0 rgba(255,255,255,.8) inset; 51 | -moz-box-shadow: 0 1px 0 rgba(255,255,255,.8) inset; 52 | box-shadow: 0 1px 0 rgba(255,255,255,.8) inset; 53 | border-top: none; 54 | text-shadow: 0 1px 0 rgba(255,255,255,.5); 55 | } 56 | 57 | .footable > thead > tr:first-child > th.footable-first-column, .footable > thead > tr:first-child > td.footable-first-column { 58 | -moz-border-radius: 6px 0 0 0; 59 | -webkit-border-radius: 6px 0 0 0; 60 | border-radius: 6px 0 0 0; 61 | } 62 | 63 | .footable > thead > tr:first-child > th.footable-last-column, .footable > thead > tr:first-child > td.footable-last-column { 64 | -moz-border-radius: 0 6px 0 0; 65 | -webkit-border-radius: 0 6px 0 0; 66 | border-radius: 0 6px 0 0; 67 | } 68 | 69 | .footable > thead > tr:first-child > th.footable-first-column.footable-last-column, .footable > thead > tr:first-child > td.footable-first-column.footable-last-column { 70 | -moz-border-radius: 6px 6px 0 0; 71 | -webkit-border-radius: 6px 6px 0 0; 72 | border-radius: 6px 6px 0 0; 73 | } 74 | 75 | .footable > tbody > tr:last-child > td.footable-first-column { 76 | -moz-border-radius: 0 0 0 6px; 77 | -webkit-border-radius: 0 0 0 6px; 78 | border-radius: 0 0 0 6px; 79 | } 80 | 81 | .footable > tbody > tr:last-child > td.footable-last-column { 82 | -moz-border-radius: 0 0 6px 0; 83 | -webkit-border-radius: 0 0 6px 0; 84 | border-radius: 0 0 6px 0; 85 | } 86 | 87 | .footable > tbody > tr:last-child > td.footable-first-column.footable-last-column { 88 | -moz-border-radius: 0 0 6px 6px; 89 | -webkit-border-radius: 0 0 6px 6px; 90 | border-radius: 0 0 6px 6px; 91 | } 92 | 93 | .footable > thead > tr > th.footable-first-column, .footable > thead > tr > td.footable-first-column, 94 | .footable > tbody > tr > td.footable-first-column { 95 | border-left: none; 96 | } 97 | 98 | .footable > tbody img { 99 | vertical-align:middle; 100 | } 101 | 102 | .footable > tfoot > tr > th, .footable > tfoot > tr > td { 103 | background-color: #dce9f9; 104 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ebf3fc), to(#dce9f9)); 105 | background-image: -webkit-linear-gradient(top, #ebf3fc, #dce9f9); 106 | background-image: -moz-linear-gradient(top, #ebf3fc, #dce9f9); 107 | background-image: -ms-linear-gradient(top, #ebf3fc, #dce9f9); 108 | background-image: -o-linear-gradient(top, #ebf3fc, #dce9f9); 109 | background-image: linear-gradient(to bottom, #ebf3fc, #dce9f9); 110 | -webkit-box-shadow: 0 1px 0 rgba(255,255,255,.8) inset; 111 | -moz-box-shadow: 0 1px 0 rgba(255,255,255,.8) inset; 112 | box-shadow: 0 1px 0 rgba(255,255,255,.8) inset; 113 | border-top: 1px solid #ccc; 114 | text-shadow: 0 1px 0 rgba(255,255,255,.5); 115 | padding: 4px; 116 | } 117 | -------------------------------------------------------------------------------- /src/lib/css/img/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/lib/css/img/down.png -------------------------------------------------------------------------------- /src/lib/css/img/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/lib/css/img/minus.png -------------------------------------------------------------------------------- /src/lib/css/img/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/lib/css/img/plus.png -------------------------------------------------------------------------------- /src/lib/css/img/sorting_sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/lib/css/img/sorting_sprite.png -------------------------------------------------------------------------------- /src/lib/css/img/trash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/lib/css/img/trash.png -------------------------------------------------------------------------------- /src/lib/css/img/up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/lib/css/img/up.png -------------------------------------------------------------------------------- /src/lib/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/lib/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png -------------------------------------------------------------------------------- /src/lib/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/lib/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png -------------------------------------------------------------------------------- /src/lib/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/lib/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png -------------------------------------------------------------------------------- /src/lib/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/lib/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png -------------------------------------------------------------------------------- /src/lib/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/lib/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png -------------------------------------------------------------------------------- /src/lib/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/lib/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png -------------------------------------------------------------------------------- /src/lib/css/smoothness/images/ui-icons_222222_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/lib/css/smoothness/images/ui-icons_222222_256x240.png -------------------------------------------------------------------------------- /src/lib/css/smoothness/images/ui-icons_2e83ff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/lib/css/smoothness/images/ui-icons_2e83ff_256x240.png -------------------------------------------------------------------------------- /src/lib/css/smoothness/images/ui-icons_454545_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/lib/css/smoothness/images/ui-icons_454545_256x240.png -------------------------------------------------------------------------------- /src/lib/css/smoothness/images/ui-icons_888888_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/lib/css/smoothness/images/ui-icons_888888_256x240.png -------------------------------------------------------------------------------- /src/lib/css/smoothness/images/ui-icons_cd0a0a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OpenLinkSoftware/OSDS_extension/6a0e6da94fd26e4035349381aa14e2baef0aaf9f/src/lib/css/smoothness/images/ui-icons_cd0a0a_256x240.png -------------------------------------------------------------------------------- /src/lib/highlight/default.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | Theme: Default 3 | Description: Original highlight.js style 4 | Author: (c) Ivan Sagalaev 5 | Maintainer: @highlightjs/core-team 6 | Website: https://highlightjs.org/ 7 | License: see project LICENSE 8 | Touched: 2021 9 | */pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#f3f3f3;color:#444}.hljs-comment{color:#697070}.hljs-punctuation,.hljs-tag{color:#444a}.hljs-tag .hljs-attr,.hljs-tag .hljs-name{color:#444}.hljs-attribute,.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-name,.hljs-selector-tag{font-weight:700}.hljs-deletion,.hljs-number,.hljs-quote,.hljs-selector-class,.hljs-selector-id,.hljs-string,.hljs-template-tag,.hljs-type{color:#800}.hljs-section,.hljs-title{color:#800;font-weight:700}.hljs-link,.hljs-operator,.hljs-regexp,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-symbol,.hljs-template-variable,.hljs-variable{color:#ab5656}.hljs-literal{color:#695}.hljs-addition,.hljs-built_in,.hljs-bullet,.hljs-code{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta .hljs-string{color:#38a}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700} -------------------------------------------------------------------------------- /src/lib/jquery-migrate-3.0.0.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery Migrate v3.0.0 | (c) jQuery Foundation and other contributors | jquery.org/license */ 2 | "undefined"==typeof jQuery.migrateMute&&(jQuery.migrateMute=!0),function(a,b){"use strict";function c(c){var d=b.console;e[c]||(e[c]=!0,a.migrateWarnings.push(c),d&&d.warn&&!a.migrateMute&&(d.warn("JQMIGRATE: "+c),a.migrateTrace&&d.trace&&d.trace()))}function d(a,b,d,e){Object.defineProperty(a,b,{configurable:!0,enumerable:!0,get:function(){return c(e),d}})}a.migrateVersion="3.0.0",function(){var c=b.console&&b.console.log&&function(){b.console.log.apply(b.console,arguments)},d=/^[12]\./;c&&(a&&!d.test(a.fn.jquery)||c("JQMIGRATE: jQuery 3.0.0+ REQUIRED"),a.migrateWarnings&&c("JQMIGRATE: Migrate plugin loaded multiple times"),c("JQMIGRATE: Migrate is installed"+(a.migrateMute?"":" with logging active")+", version "+a.migrateVersion))}();var e={};a.migrateWarnings=[],void 0===a.migrateTrace&&(a.migrateTrace=!0),a.migrateReset=function(){e={},a.migrateWarnings.length=0},"BackCompat"===document.compatMode&&c("jQuery is not compatible with Quirks Mode");var f=a.fn.init,g=a.isNumeric,h=a.find,i=/\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/,j=/\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/g;a.fn.init=function(a){var b=Array.prototype.slice.call(arguments);return"string"==typeof a&&"#"===a&&(c("jQuery( '#' ) is not a valid selector"),b[0]=[]),f.apply(this,b)},a.fn.init.prototype=a.fn,a.find=function(a){var b=Array.prototype.slice.call(arguments);if("string"==typeof a&&i.test(a))try{document.querySelector(a)}catch(d){a=a.replace(j,function(a,b,c,d){return"["+b+c+'"'+d+'"]'});try{document.querySelector(a),c("Attribute selector with '#' must be quoted: "+b[0]),b[0]=a}catch(e){c("Attribute selector with '#' was not fixed: "+b[0])}}return h.apply(this,b)};var k;for(k in h)Object.prototype.hasOwnProperty.call(h,k)&&(a.find[k]=h[k]);a.fn.size=function(){return c("jQuery.fn.size() is deprecated; use the .length property"),this.length},a.parseJSON=function(){return c("jQuery.parseJSON is deprecated; use JSON.parse"),JSON.parse.apply(null,arguments)},a.isNumeric=function(b){function d(b){var c=b&&b.toString();return!a.isArray(b)&&c-parseFloat(c)+1>=0}var e=g(b),f=d(b);return e!==f&&c("jQuery.isNumeric() should not be called on constructed objects"),f},d(a,"unique",a.uniqueSort,"jQuery.unique is deprecated, use jQuery.uniqueSort"),d(a.expr,"filters",a.expr.pseudos,"jQuery.expr.filters is now jQuery.expr.pseudos"),d(a.expr,":",a.expr.pseudos,'jQuery.expr[":"] is now jQuery.expr.pseudos');var l=a.ajax;a.ajax=function(){var a=l.apply(this,arguments);return a.promise&&(d(a,"success",a.done,"jQXHR.success is deprecated and removed"),d(a,"error",a.fail,"jQXHR.error is deprecated and removed"),d(a,"complete",a.always,"jQXHR.complete is deprecated and removed")),a};var m=a.fn.removeAttr,n=a.fn.toggleClass,o=/\S+/g;a.fn.removeAttr=function(b){var d=this;return a.each(b.match(o),function(b,e){a.expr.match.bool.test(e)&&(c("jQuery.fn.removeAttr no longer sets boolean properties: "+e),d.prop(e,!1))}),m.apply(this,arguments)},a.fn.toggleClass=function(b){return void 0!==b&&"boolean"!=typeof b?n.apply(this,arguments):(c("jQuery.fn.toggleClass( boolean ) is deprecated"),this.each(function(){var c=this.getAttribute&&this.getAttribute("class")||"";c&&a.data(this,"__className__",c),this.setAttribute&&this.setAttribute("class",c||b===!1?"":a.data(this,"__className__")||"")}))};var p=!1;a.swap&&a.each(["height","width","reliableMarginRight"],function(b,c){var d=a.cssHooks[c]&&a.cssHooks[c].get;d&&(a.cssHooks[c].get=function(){var a;return p=!0,a=d.apply(this,arguments),p=!1,a})}),a.swap=function(a,b,d,e){var f,g,h={};p||c("jQuery.swap() is undocumented and deprecated");for(g in b)h[g]=a.style[g],a.style[g]=b[g];f=d.apply(a,e||[]);for(g in b)a.style[g]=h[g];return f};var q=a.data;a.data=function(b,d,e){var f;return d&&d!==a.camelCase(d)&&(f=a.hasData(b)&&q.call(this,b),f&&d in f)?(c("jQuery.data() always sets/gets camelCased names: "+d),arguments.length>2&&(f[d]=e),f[d]):q.apply(this,arguments)};var r=a.Tween.prototype.run;a.Tween.prototype.run=function(b){a.easing[this.easing].length>1&&(c('easing function "jQuery.easing.'+this.easing.toString()+'" should use only first argument'),a.easing[this.easing]=a.easing[this.easing].bind(a.easing,b,this.options.duration*b,0,1,this.options.duration)),r.apply(this,arguments)};var s=a.fn.load,t=a.event.fix;a.event.props=[],a.event.fixHooks={},a.event.fix=function(b){var d,e=b.type,f=this.fixHooks[e],g=a.event.props;if(g.length)for(c("jQuery.event.props are deprecated and removed: "+g.join());g.length;)a.event.addProp(g.pop());if(f&&!f._migrated_&&(f._migrated_=!0,c("jQuery.event.fixHooks are deprecated and removed: "+e),(g=f.props)&&g.length))for(;g.length;)a.event.addProp(g.pop());return d=t.call(this,b),f&&f.filter?f.filter(d,b):d},a.each(["load","unload","error"],function(b,d){a.fn[d]=function(){var a=Array.prototype.slice.call(arguments,0);return"load"===d&&"string"==typeof a[0]?s.apply(this,a):(c("jQuery.fn."+d+"() is deprecated"),a.splice(0,0,d),arguments.length?this.on.apply(this,a):(this.triggerHandler.apply(this,a),this))}}),a(function(){a(document).triggerHandler("ready")}),a.event.special.ready={setup:function(){this===document&&c("'ready' event is deprecated")}},a.fn.extend({bind:function(a,b,d){return c("jQuery.fn.bind() is deprecated"),this.on(a,null,b,d)},unbind:function(a,b){return c("jQuery.fn.unbind() is deprecated"),this.off(a,null,b)},delegate:function(a,b,d,e){return c("jQuery.fn.delegate() is deprecated"),this.on(b,a,d,e)},undelegate:function(a,b,d){return c("jQuery.fn.undelegate() is deprecated"),1===arguments.length?this.off(a,"**"):this.off(b,a||"**",d)}});var u=a.fn.offset;a.fn.offset=function(){var b,d=this[0],e={top:0,left:0};return d&&d.nodeType?(b=(d.ownerDocument||document).documentElement,a.contains(b,d)?u.apply(this,arguments):(c("jQuery.fn.offset() requires an element connected to a document"),e)):(c("jQuery.fn.offset() requires a valid DOM element"),e)};var v=a.param;a.param=function(b,d){var e=a.ajaxSettings&&a.ajaxSettings.traditional;return void 0===d&&e&&(c("jQuery.param() no longer uses jQuery.ajaxSettings.traditional"),d=e),v.call(this,b,d)};var w=a.fn.andSelf||a.fn.addBack;a.fn.andSelf=function(){return c("jQuery.fn.andSelf() replaced by jQuery.fn.addBack()"),w.apply(this,arguments)};var x=a.Deferred,y=[["resolve","done",a.Callbacks("once memory"),a.Callbacks("once memory"),"resolved"],["reject","fail",a.Callbacks("once memory"),a.Callbacks("once memory"),"rejected"],["notify","progress",a.Callbacks("memory"),a.Callbacks("memory")]];a.Deferred=function(b){var d=x(),e=d.promise();return d.pipe=e.pipe=function(){var b=arguments;return c("deferred.pipe() is deprecated"),a.Deferred(function(c){a.each(y,function(f,g){var h=a.isFunction(b[f])&&b[f];d[g[1]](function(){var b=h&&h.apply(this,arguments);b&&a.isFunction(b.promise)?b.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[g[0]+"With"](this===e?c.promise():this,h?[b]:arguments)})}),b=null}).promise()},b&&b.call(d,d),d}}(jQuery,window); -------------------------------------------------------------------------------- /src/lib/md_view.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | preview 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/lib/microdatajs/jquery.microdata.js: -------------------------------------------------------------------------------- 1 | /* -*- mode: js; js-indent-level: 2; indent-tabs-mode: nil -*- */ 2 | 3 | 'use strict'; 4 | 5 | (function(){ 6 | var $ = jQuery; 7 | 8 | $.microdata = {}; 9 | 10 | // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#valid-time-string 11 | function validTimeStringLength(s) { 12 | var m = /^(\d\d):(\d\d)(:(\d\d)(\.\d+)?)?/.exec(s); 13 | if (m && m[1]<=23 && m[2]<=59 && (!m[4] || m[4]<=59)) 14 | return m[0].length; 15 | return 0; 16 | } 17 | 18 | function isValidTimeString(s) { 19 | return s && validTimeStringLength(s) == s.length; 20 | } 21 | 22 | // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#number-of-days-in-month-month-of-year-year 23 | function daysInMonth(year, month) { 24 | if (month==1 || month==3 || month==5 || month==7 || 25 | month==8 || month==10 || month==12) { 26 | return 31; 27 | } else if (month==4 || month==6 || month==9 || month==11) { 28 | return 30; 29 | } else if (month == 2 && (year%400==0 || (year%4==0 && year%100!=0))) { 30 | return 29; 31 | } else { 32 | return 28; 33 | } 34 | } 35 | 36 | // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#valid-date-string 37 | function validDateStringLength(s) { 38 | var m = /^(\d{4,})-(\d\d)-(\d\d)/.exec(s); 39 | if (m && m[1]>=1 && m[2]>=1 && m[2]<=12 && m[3]>=1 && m[3]<=daysInMonth(m[1],m[2])) 40 | return m[0].length; 41 | return 0; 42 | } 43 | 44 | function isValidDateString(s) { 45 | return s && validDateStringLength(s) == s.length; 46 | } 47 | 48 | // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#valid-global-date-and-time-string 49 | function isValidGlobalDateAndTimeString(s) { 50 | var skip = validDateStringLength(s); 51 | if (skip && s[skip] == 'T') { 52 | s = s.substr(skip+1); 53 | skip = validTimeStringLength(s); 54 | if (skip) { 55 | s = s.substr(skip); 56 | if (s == 'Z') 57 | return true; 58 | var m = /^[+-](\d\d):(\d\d)$/.exec(s); 59 | if (m && m[1]<=23 && m[2]<=59) 60 | return true; 61 | } 62 | } 63 | return false; 64 | } 65 | 66 | $.microdata.isValidGlobalDateAndTimeString = isValidGlobalDateAndTimeString; 67 | $.microdata.isValidDateString = isValidDateString; 68 | 69 | function splitTokens(s) { 70 | if (s && /\S/.test(s)) 71 | return s.replace(/^\s+|\s+$/g,'').split(/\s+/); 72 | return []; 73 | } 74 | 75 | function getItems(types) { 76 | var selector = $.map(splitTokens(types), function(t) { 77 | return '[itemtype~="'+t.replace(/"/g, '\\"')+'"]'; 78 | }).join('') || '*'; 79 | // filter results to only match top-level items. 80 | // because [attr] selector doesn't work in IE we have to 81 | // filter the elements. http://dev.jquery.com/ticket/5637 82 | return $(selector, this).filter(function() { 83 | return (this.getAttribute('itemscope') != null && 84 | this.getAttribute('itemprop') == null); 85 | }); 86 | } 87 | 88 | function getSubItems(types) { 89 | var selector = $.map(splitTokens(types), function(t) { 90 | return '[itemtype~="'+t.replace(/"/g, '\\"')+'"]'; 91 | }).join('') || '*'; 92 | // filter results to only match top-level items. 93 | // because [attr] selector doesn't work in IE we have to 94 | // filter the elements. http://dev.jquery.com/ticket/5637 95 | return $(this).children(selector).filter(function() { 96 | return (this.getAttribute('itemscope') != null && 97 | this.getAttribute('itemprop') == null); 98 | }); 99 | } 100 | 101 | // find the furthest ancestor (usually Document) 102 | function ancestor(node) { 103 | while (node.parentNode) 104 | node = node.parentNode; 105 | return node; 106 | } 107 | 108 | function resolve(elm, attr) { 109 | // in order to handle and attributes which aren't properly 110 | // reflected as URLs, insert a temporary element just before 111 | // elm and resolve using its src attribute. the element must 112 | // be created using the parent document due IE security policy. 113 | var url = elm.getAttribute(attr); 114 | if (!url) 115 | return ''; 116 | var a = ancestor(elm); 117 | var p = elm.parentNode; 118 | var img = (a.createElement ? a : document).createElement('img'); 119 | try { 120 | img.setAttribute('src', url); 121 | if (p) 122 | p.insertBefore(img, elm); 123 | url = img.src; 124 | if (p) 125 | p.removeChild(img); 126 | } catch (e) { 127 | // IE>6 throws "TypeError: Access is denied." for mailto: 128 | // URLs. This is annoying, but harmless to ignore. 129 | } 130 | return url; 131 | } 132 | 133 | function tokenList(attr) { 134 | return function() { 135 | var list = splitTokens(this.attr(attr)); 136 | list.contains = function(token) { 137 | return $.inArray(token, this) != -1; 138 | }; 139 | return list; 140 | }; 141 | } 142 | 143 | function itemValue() { 144 | var elm = this[0]; 145 | if (elm.getAttribute('itemprop') == null) 146 | return null; 147 | if (this.itemScope()) { 148 | return elm; // or a new jQuery object? 149 | } 150 | switch (elm.tagName.toUpperCase()) { 151 | case 'META': 152 | return this.attr('content') || ''; 153 | case 'AUDIO': 154 | case 'EMBED': 155 | case 'IFRAME': 156 | case 'IMG': 157 | case 'SOURCE': 158 | case 'TRACK': 159 | case 'VIDEO': 160 | return resolve(elm, 'src'); 161 | case 'A': 162 | case 'AREA': 163 | case 'LINK': 164 | return resolve(elm, 'href'); 165 | case 'OBJECT': 166 | return resolve(elm, 'data'); 167 | case 'DATA': 168 | return this.attr('value') || ''; 169 | case 'TIME': 170 | var datetime = elm.getAttribute('datetime'); 171 | if (datetime != null) 172 | return datetime; 173 | default: 174 | return this.text(); 175 | } 176 | } 177 | 178 | function properties(name) { 179 | // Find all elements that add properties to the item, optionally 180 | // filtered by a property name. Look in the subtrees rooted at the 181 | // item itself and any itemref'd elements. An item can never have 182 | // itself as a property, but circular reference is possible. 183 | 184 | var props = []; 185 | 186 | function crawl(root) { 187 | var toTraverse = [root]; 188 | 189 | function traverse(node) { 190 | for (var i = 0; i < toTraverse.length; i++) { 191 | if (toTraverse[i] == node) 192 | toTraverse.splice(i--, 1); 193 | } 194 | var $node = $(node); 195 | if (node != root) { 196 | var names = $node.itemProp(); 197 | if (names.length) { 198 | if (!name || names.contains(name)) 199 | props.push(node); 200 | } 201 | if ($node.itemScope()) 202 | return; 203 | } 204 | $node.children().each(function() { 205 | traverse(this); 206 | }); 207 | } 208 | 209 | var context = ancestor(root); 210 | $.each($(root).itemRef(), function(i, id) { 211 | var $ref = $('#'+id, context); 212 | if ($ref.length) 213 | toTraverse.push($ref[0]); 214 | }); 215 | $.unique(toTraverse); 216 | 217 | while (toTraverse.length) { 218 | traverse(toTraverse[0]); 219 | } 220 | } 221 | 222 | if (this.itemScope()) 223 | crawl(this[0]); 224 | 225 | // properties are already sorted in tree order 226 | return $(props); 227 | } 228 | 229 | // feature detection to use native support where available 230 | var t = $('')[0]; 231 | 232 | $.fn.extend({ 233 | items: document.getItems && t.itemType && t.itemType.contains ? function(types) { 234 | var doc = this[0]; 235 | if (doc.getItems) 236 | return $(types ? doc.getItems(types) : doc.getItems()); 237 | return getItems.call(this, types); 238 | } : getItems, 239 | sub_items: getSubItems, 240 | itemScope: t.itemScope ? function() { 241 | return this[0].itemScope; 242 | } : function () { 243 | return this[0].getAttribute('itemscope') != null; 244 | }, 245 | itemType: t.itemType && t.itemType.contains ? function() { 246 | return this[0].itemType; 247 | } : tokenList('itemtype'), 248 | itemId: t.itemId == 'id' ? function() { 249 | return this[0].itemId; 250 | } : function () { 251 | return resolve(this[0], 'itemid'); 252 | }, 253 | itemProp: t.itemProp && t.itemProp.contains ? function() { 254 | return this[0].itemProp; 255 | } : tokenList('itemprop'), 256 | itemRef: t.itemRef && t.itemRef.contains ? function() { 257 | return this[0].itemRef; 258 | } : tokenList('itemref'), 259 | itemValue: t.itemValue == t && t.value == 'value' ? function() { 260 | return this[0].itemValue; 261 | } : itemValue, 262 | properties: t.properties && t.properties.namedItem ? function(name) { 263 | return $(name ? this[0].properties.namedItem(name) : this[0].properties); 264 | } : properties 265 | }); 266 | })(); 267 | -------------------------------------------------------------------------------- /src/lib/microdatajs/jquery.microdata.json.js: -------------------------------------------------------------------------------- 1 | /* -*- mode: js; js-indent-level: 2; indent-tabs-mode: nil -*- */ 2 | 3 | 'use strict'; 4 | 5 | // http://www.whatwg.org/specs/web-apps/current-work/multipage/microdata.html#json 6 | jQuery.microdata.json = function(selector, format) { 7 | var $ = jQuery; 8 | var memo_scope = []; 9 | 10 | function getObject(item, memory) { 11 | var $item = $(item); 12 | var result = {}; 13 | var types = $item.itemType(); 14 | 15 | if (types.length) 16 | result.type = $(types).toArray(); 17 | 18 | if ($item.itemId()) 19 | result.id = $item.itemId(); 20 | 21 | result.properties = {}; 22 | 23 | $item.properties().each(function(i, elem) { 24 | var $elem = $(elem); 25 | var value; 26 | if ($elem.itemScope()) { 27 | if ($.inArray(elem, memory) != -1) { 28 | value = 'ERROR'; 29 | } else { 30 | memory.push(item); 31 | memo_scope.push(elem); 32 | value = getObject(elem, memory); 33 | memory.pop(); 34 | } 35 | } else { 36 | value = $elem.itemValue(); 37 | } 38 | 39 | $.each($elem.itemProp(), function(i, prop) { 40 | if (!result.properties[prop]) 41 | result.properties[prop] = []; 42 | result.properties[prop].push(value); 43 | }); 44 | }); 45 | 46 | 47 | var add_items = $item.sub_items().not($item.properties()).not($(memo_scope)); 48 | 49 | add_items.each(function(i, elem) { 50 | var $elem = $(elem); 51 | var value; 52 | 53 | //only unlinked itemscope checked 54 | if (!$elem.itemScope()) 55 | return; 56 | 57 | if ($.inArray(elem, memo_scope) != -1) 58 | return; 59 | 60 | if ($.inArray(elem, memory) != -1) { 61 | value = 'ERROR'; 62 | } else { 63 | memory.push(item); 64 | memo_scope.push(elem); 65 | value = getObject(elem, memory); 66 | memory.pop(); 67 | } 68 | 69 | //try fix unnamed items 70 | if ($elem.itemProp().length==0) { 71 | var id = ":unnamed"; 72 | if (!result.properties[id]) 73 | result.properties[id] = []; 74 | result.properties[id].push(value); 75 | 76 | } else { 77 | $.each($elem.itemProp(), function(i, prop) { 78 | if (!result.properties[prop]) 79 | result.properties[prop] = []; 80 | result.properties[prop].push(value); 81 | }); 82 | } 83 | }); 84 | 85 | return result; 86 | } 87 | 88 | function processItemScope($items, result) { 89 | $items.each(function(i, item) { 90 | var $item = $(item); 91 | if ($item.itemScope()) { 92 | result.items.push(getObject(item, [])); 93 | // JCD: Process any top-level descendant itemscopes, but where the node doesn't directly contain an itemprop attribute. 94 | // var descendants = $item.find('[itemscope]').not($item.find('[itemscope] [itemscope]')).not($item.find('[itemprop]')); 95 | var descendants = $item.find('[itemscope]').not($item.find('[itemscope] [itemscope]')).not($item.find('[itemprop]')).not($(memo_scope)); 96 | processItemScope(descendants, result); 97 | } 98 | }); 99 | return result; 100 | } 101 | 102 | var result = {}; 103 | result.items = []; 104 | var $items = selector ? $(selector) : $(document).items(); 105 | 106 | result = processItemScope($items, result); 107 | 108 | return format ? format(result) : JSON.stringify(result); 109 | }; 110 | -------------------------------------------------------------------------------- /src/lib/original/FileSaver.js: -------------------------------------------------------------------------------- 1 | /* FileSaver.js 2 | * A saveAs() FileSaver implementation. 3 | * 1.1.20151003 4 | * 5 | * By Eli Grey, http://eligrey.com 6 | * License: MIT 7 | * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md 8 | */ 9 | 10 | /*global self */ 11 | /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */ 12 | 13 | /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ 14 | 15 | var saveAs = saveAs || (function(view) { 16 | "use strict"; 17 | // IE <10 is explicitly unsupported 18 | if (typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) { 19 | return; 20 | } 21 | var 22 | doc = view.document 23 | // only get URL when necessary in case Blob.js hasn't overridden it yet 24 | , get_URL = function() { 25 | return view.URL || view.webkitURL || view; 26 | } 27 | , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a") 28 | , can_use_save_link = "download" in save_link 29 | , click = function(node) { 30 | var event = new MouseEvent("click"); 31 | node.dispatchEvent(event); 32 | } 33 | , is_safari = /Version\/[\d\.]+.*Safari/.test(navigator.userAgent) 34 | , webkit_req_fs = view.webkitRequestFileSystem 35 | , req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem 36 | , throw_outside = function(ex) { 37 | (view.setImmediate || view.setTimeout)(function() { 38 | throw ex; 39 | }, 0); 40 | } 41 | , force_saveable_type = "application/octet-stream" 42 | , fs_min_size = 0 43 | // See https://code.google.com/p/chromium/issues/detail?id=375297#c7 and 44 | // https://github.com/eligrey/FileSaver.js/commit/485930a#commitcomment-8768047 45 | // for the reasoning behind the timeout and revocation flow 46 | , arbitrary_revoke_timeout = 500 // in ms 47 | , revoke = function(file) { 48 | var revoker = function() { 49 | if (typeof file === "string") { // file is an object URL 50 | get_URL().revokeObjectURL(file); 51 | } else { // file is a File 52 | file.remove(); 53 | } 54 | }; 55 | if (view.chrome) { 56 | revoker(); 57 | } else { 58 | setTimeout(revoker, arbitrary_revoke_timeout); 59 | } 60 | } 61 | , dispatch = function(filesaver, event_types, event) { 62 | event_types = [].concat(event_types); 63 | var i = event_types.length; 64 | while (i--) { 65 | var listener = filesaver["on" + event_types[i]]; 66 | if (typeof listener === "function") { 67 | try { 68 | listener.call(filesaver, event || filesaver); 69 | } catch (ex) { 70 | throw_outside(ex); 71 | } 72 | } 73 | } 74 | } 75 | , auto_bom = function(blob) { 76 | // prepend BOM for UTF-8 XML and text/* types (including HTML) 77 | if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) { 78 | return new Blob(["\ufeff", blob], {type: blob.type}); 79 | } 80 | return blob; 81 | } 82 | , FileSaver = function(blob, name, no_auto_bom) { 83 | if (!no_auto_bom) { 84 | blob = auto_bom(blob); 85 | } 86 | // First try a.download, then web filesystem, then object URLs 87 | var 88 | filesaver = this 89 | , type = blob.type 90 | , blob_changed = false 91 | , object_url 92 | , target_view 93 | , dispatch_all = function() { 94 | dispatch(filesaver, "writestart progress write writeend".split(" ")); 95 | } 96 | // on any filesys errors revert to saving with object URLs 97 | , fs_error = function() { 98 | if (target_view && is_safari && typeof FileReader !== "undefined") { 99 | // Safari doesn't allow downloading of blob urls 100 | var reader = new FileReader(); 101 | reader.onloadend = function() { 102 | var base64Data = reader.result; 103 | target_view.location.href = "data:attachment/file" + base64Data.slice(base64Data.search(/[,;]/)); 104 | filesaver.readyState = filesaver.DONE; 105 | dispatch_all(); 106 | }; 107 | reader.readAsDataURL(blob); 108 | filesaver.readyState = filesaver.INIT; 109 | return; 110 | } 111 | // don't create more object URLs than needed 112 | if (blob_changed || !object_url) { 113 | object_url = get_URL().createObjectURL(blob); 114 | } 115 | if (target_view) { 116 | target_view.location.href = object_url; 117 | } else { 118 | var new_tab = view.open(object_url, "_blank"); 119 | if (new_tab == undefined && is_safari) { 120 | //Apple do not allow window.open, see http://bit.ly/1kZffRI 121 | view.location.href = object_url 122 | } 123 | } 124 | filesaver.readyState = filesaver.DONE; 125 | dispatch_all(); 126 | revoke(object_url); 127 | } 128 | , abortable = function(func) { 129 | return function() { 130 | if (filesaver.readyState !== filesaver.DONE) { 131 | return func.apply(this, arguments); 132 | } 133 | }; 134 | } 135 | , create_if_not_found = {create: true, exclusive: false} 136 | , slice 137 | ; 138 | filesaver.readyState = filesaver.INIT; 139 | if (!name) { 140 | name = "download"; 141 | } 142 | if (can_use_save_link) { 143 | object_url = get_URL().createObjectURL(blob); 144 | setTimeout(function() { 145 | save_link.href = object_url; 146 | save_link.download = name; 147 | click(save_link); 148 | dispatch_all(); 149 | revoke(object_url); 150 | filesaver.readyState = filesaver.DONE; 151 | }); 152 | return; 153 | } 154 | // Object and web filesystem URLs have a problem saving in Google Chrome when 155 | // viewed in a tab, so I force save with application/octet-stream 156 | // http://code.google.com/p/chromium/issues/detail?id=91158 157 | // Update: Google errantly closed 91158, I submitted it again: 158 | // https://code.google.com/p/chromium/issues/detail?id=389642 159 | if (view.chrome && type && type !== force_saveable_type) { 160 | slice = blob.slice || blob.webkitSlice; 161 | blob = slice.call(blob, 0, blob.size, force_saveable_type); 162 | blob_changed = true; 163 | } 164 | // Since I can't be sure that the guessed media type will trigger a download 165 | // in WebKit, I append .download to the filename. 166 | // https://bugs.webkit.org/show_bug.cgi?id=65440 167 | if (webkit_req_fs && name !== "download") { 168 | name += ".download"; 169 | } 170 | if (type === force_saveable_type || webkit_req_fs) { 171 | target_view = view; 172 | } 173 | if (!req_fs) { 174 | fs_error(); 175 | return; 176 | } 177 | fs_min_size += blob.size; 178 | req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) { 179 | fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) { 180 | var save = function() { 181 | dir.getFile(name, create_if_not_found, abortable(function(file) { 182 | file.createWriter(abortable(function(writer) { 183 | writer.onwriteend = function(event) { 184 | target_view.location.href = file.toURL(); 185 | filesaver.readyState = filesaver.DONE; 186 | dispatch(filesaver, "writeend", event); 187 | revoke(file); 188 | }; 189 | writer.onerror = function() { 190 | var error = writer.error; 191 | if (error.code !== error.ABORT_ERR) { 192 | fs_error(); 193 | } 194 | }; 195 | "writestart progress write abort".split(" ").forEach(function(event) { 196 | writer["on" + event] = filesaver["on" + event]; 197 | }); 198 | writer.write(blob); 199 | filesaver.abort = function() { 200 | writer.abort(); 201 | filesaver.readyState = filesaver.DONE; 202 | }; 203 | filesaver.readyState = filesaver.WRITING; 204 | }), fs_error); 205 | }), fs_error); 206 | }; 207 | dir.getFile(name, {create: false}, abortable(function(file) { 208 | // delete file if it already exists 209 | file.remove(); 210 | save(); 211 | }), abortable(function(ex) { 212 | if (ex.code === ex.NOT_FOUND_ERR) { 213 | save(); 214 | } else { 215 | fs_error(); 216 | } 217 | })); 218 | }), fs_error); 219 | }), fs_error); 220 | } 221 | , FS_proto = FileSaver.prototype 222 | , saveAs = function(blob, name, no_auto_bom) { 223 | return new FileSaver(blob, name, no_auto_bom); 224 | } 225 | ; 226 | // IE 10+ (native saveAs) 227 | if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) { 228 | return function(blob, name, no_auto_bom) { 229 | if (!no_auto_bom) { 230 | blob = auto_bom(blob); 231 | } 232 | return navigator.msSaveOrOpenBlob(blob, name || "download"); 233 | }; 234 | } 235 | 236 | FS_proto.abort = function() { 237 | var filesaver = this; 238 | filesaver.readyState = filesaver.DONE; 239 | dispatch(filesaver, "abort"); 240 | }; 241 | FS_proto.readyState = FS_proto.INIT = 0; 242 | FS_proto.WRITING = 1; 243 | FS_proto.DONE = 2; 244 | 245 | FS_proto.error = 246 | FS_proto.onwritestart = 247 | FS_proto.onprogress = 248 | FS_proto.onwrite = 249 | FS_proto.onabort = 250 | FS_proto.onerror = 251 | FS_proto.onwriteend = 252 | null; 253 | 254 | return saveAs; 255 | }( 256 | typeof self !== "undefined" && self 257 | || typeof window !== "undefined" && window 258 | || this.content 259 | )); 260 | // `self` is undefined in Firefox for Android content script context 261 | // while `this` is nsIContentFrameMessageManager 262 | // with an attribute `content` that corresponds to the window 263 | 264 | if (typeof module !== "undefined" && module.exports) { 265 | module.exports.saveAs = saveAs; 266 | } else if ((typeof define !== "undefined" && define !== null) && (define.amd != null)) { 267 | define([], function() { 268 | return saveAs; 269 | }); 270 | } 271 | -------------------------------------------------------------------------------- /src/lib/original/jquery.microdata.json.js: -------------------------------------------------------------------------------- 1 | /* -*- mode: js; js-indent-level: 2; indent-tabs-mode: nil -*- */ 2 | 3 | 'use strict'; 4 | 5 | // http://www.whatwg.org/specs/web-apps/current-work/multipage/microdata.html#json 6 | jQuery.microdata.json = function(selector, format) { 7 | var $ = jQuery; 8 | 9 | function getObject(item, memory) { 10 | var $item = $(item); 11 | var result = {}; 12 | var types = $item.itemType(); 13 | if (types.length) 14 | result.type = $(types).toArray(); 15 | if ($item.itemId()) 16 | result.id = $item.itemId(); 17 | result.properties = {}; 18 | $item.properties().each(function(i, elem) { 19 | var $elem = $(elem); 20 | var value; 21 | if ($elem.itemScope()) { 22 | if ($.inArray(elem, memory) != -1) { 23 | value = 'ERROR'; 24 | } else { 25 | memory.push(item); 26 | value = getObject(elem, memory); 27 | memory.pop(); 28 | } 29 | } else { 30 | value = $elem.itemValue(); 31 | } 32 | $.each($elem.itemProp(), function(i, prop) { 33 | if (!result.properties[prop]) 34 | result.properties[prop] = []; 35 | result.properties[prop].push(value); 36 | }); 37 | }); 38 | return result; 39 | } 40 | 41 | function processItemScope($items, result) { 42 | $items.each(function(i, item) { 43 | var $item = $(item); 44 | if ($item.itemScope()) { 45 | result.items.push(getObject(item, [])); 46 | // JCD: Process any top-level descendant itemscopes, but where the node doesn't directly contain an itemprop attribute. 47 | var descendants = $item.find('[itemscope]').not($item.find('[itemscope] [itemscope]')).not($item.find('[itemprop]')); 48 | processItemScope(descendants, result); 49 | } 50 | }); 51 | return result; 52 | } 53 | 54 | var result = {}; 55 | result.items = []; 56 | var $items = selector ? $(selector) : $(document).items(); 57 | 58 | result = processItemScope($items, result); 59 | 60 | return format ? format(result) : JSON.stringify(result); 61 | }; 62 | -------------------------------------------------------------------------------- /src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "OpenLink Structured Data Sniffer", 3 | "short_name": "OSD Sniffer", 4 | "author":"OpenLink Software", 5 | "homepage_url": "http://osds.openlinksw.com/", 6 | "version": "3.4.21", 7 | "manifest_version": 3, 8 | "minimum_chrome_version": "88", 9 | "description": "Reveals structured metadata (Microdata, RDFa, JSON-LD, Turtle, etc.) embedded within HTML documents.", 10 | "icons": { 11 | "16": "images/icon16.png", 12 | "48": "images/icon48.png", 13 | "128": "images/icon128.png" }, 14 | "action": { 15 | "default_icon": "images/icon16.png", 16 | "default_title": "Show Document Metadata", 17 | "default_popup": "panel.html" 18 | }, 19 | "background": { 20 | "service_worker": "service_worker.js" 21 | }, 22 | "options_ui": { 23 | "page": "options.html", 24 | "open_in_tab": true 25 | }, 26 | "content_scripts": [ 27 | { 28 | "matches": ["file:///*/*","*://*/*"], 29 | "js": ["lib/jquery-3.1.0.min.js", "lib/microdatajs/jquery.microdata.js", 30 | "lib/microdatajs/jquery.microdata.json.js", "lib/RDFa.js", "lib/n3-browser.js", 31 | "lib/jquery.mark.js", "lib/namespace.js", "lib/posh.js", "utils.js", "helpers_ui.js", 32 | "browser.js", "settings.js", "sniffer_nano.js", "super_links.js", 33 | "sniffer.js", "chat-inject.js", "social_sniffer.js"], 34 | "css": ["content.css"], 35 | "run_at": "document_idle" 36 | }, 37 | { 38 | "matches": ["https://openlinksoftware.github.io/*"], 39 | "js": ["browser.js", "lib/solid-client-authn.bundle.js", "oidc-webid-inject.js"], 40 | "run_at": "document_start" 41 | } 42 | ], 43 | "host_permissions": [ 44 | "" 45 | ], 46 | "permissions": [ 47 | "storage", 48 | "webRequest", 49 | "contextMenus", 50 | "scripting", 51 | "declarativeNetRequest" 52 | ], 53 | "content_security_policy": { 54 | "extension_pages": "script-src 'self' ; object-src 'self'; style-src 'self' 'unsafe-inline' chrome-extension://lib https://solid.openlinksw.com; media-src 'self' blob: https://* http://* 'unsafe-inline' chrome-extension://lib ;" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/manifest.json.ff: -------------------------------------------------------------------------------- 1 | { 2 | "name": "OpenLink Structured Data Sniffer", 3 | "short_name": "osds", 4 | "author":"OpenLink Software", 5 | "homepage_url": "http://osds.openlinksw.com/", 6 | "version": "3.4.21", 7 | "manifest_version": 3, 8 | "minimum_chrome_version": "88", 9 | "description": "Reveals structured metadata (Microdata, RDFa, JSON-LD, Turtle, etc.) embedded within HTML documents.", 10 | "browser_specific_settings": { 11 | "gecko": { 12 | "id": "osds@openlinksw.com", 13 | "strict_min_version": "109.0" 14 | } 15 | }, 16 | "icons": { 17 | "16": "images/icon16.png", 18 | "48": "images/icon48.png", 19 | "128": "images/icon128.png" }, 20 | "action": { 21 | "default_icon": "images/icon16.png", 22 | "default_title": "Show Document Metadata", 23 | "default_popup": "panel.html" 24 | }, 25 | "background": { 26 | "scripts": ["lib/gpt3-encoder.js", "browser.js", "settings.js", "utils.js", "helpers.js", 27 | "lib/solid-client-authn.bundle.js", "OidcWebid.js", "chat-srv.js", "background_web.js", 28 | "background.js", "service_worker_ff.js"] 29 | }, 30 | "options_ui": { 31 | "page": "options.html", 32 | "open_in_tab": true 33 | }, 34 | "content_scripts": [ 35 | { 36 | "matches": ["file:///*/*","*://*/*"], 37 | "js": ["lib/jquery-3.1.0.min.js", "lib/microdatajs/jquery.microdata.js", 38 | "lib/microdatajs/jquery.microdata.json.js", "lib/RDFa.js", "lib/n3-browser.js", 39 | "lib/jquery.mark.js", "lib/namespace.js", "lib/posh.js", "utils.js", "helpers_ui.js", 40 | "browser.js", "settings.js", "sniffer_nano.js", "super_links.js", 41 | "sniffer.js", "chat-inject.js", "social_sniffer.js"], 42 | "css": ["content.css"], 43 | "run_at": "document_idle" 44 | }, 45 | { 46 | "matches": ["https://openlinksoftware.github.io/*"], 47 | "js": ["browser.js", "lib/solid-client-authn.bundle.js", "oidc-webid-inject.js"], 48 | "run_at": "document_start" 49 | } 50 | ], 51 | "host_permissions": [ 52 | "" 53 | ], 54 | "permissions": [ 55 | "storage", 56 | "webRequest", 57 | "contextMenus", 58 | "scripting", 59 | "declarativeNetRequest" 60 | ], 61 | "content_security_policy": { 62 | "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self' moz-extension://lib; style-src 'self' 'unsafe-inline' moz-extension://lib https://solid.openlinksw.com; media-src 'self' 'unsafe-inline' moz-extension://lib ;" 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/manifest.json.sf: -------------------------------------------------------------------------------- 1 | { 2 | "name": "OpenLink Structured Data Sniffer", 3 | "short_name": "OSD Sniffer", 4 | "author":"OpenLink Software", 5 | "homepage_url": "http://osds.openlinksw.com/", 6 | "version": "3.4.21", 7 | "manifest_version": 3, 8 | "minimum_chrome_version": "88", 9 | "description": "Reveals structured metadata (Microdata, RDFa, JSON-LD, Turtle, etc.) embedded within HTML documents.", 10 | "browser_specific_settings": { 11 | "safari": { 12 | "strict_min_version": "15.4", 13 | "strict_max_version": "*" 14 | } 15 | }, 16 | "icons": { 17 | "16": "images/icon16.png", 18 | "48": "images/icon48.png", 19 | "128": "images/icon128.png" }, 20 | "action": { 21 | "default_icon": "images/icon16.png", 22 | "default_title": "Show Document Metadata", 23 | "default_popup": "panel.html" 24 | }, 25 | "background": { 26 | "persistent": false, 27 | "scripts": ["lib/gpt3-encoder.js", "browser.js", "settings.js", "utils.js", "helpers.js", 28 | "lib/solid-client-authn.bundle.js", "OidcWebid.js", "chat-srv.js", "background_web.js", 29 | "background.js", "service_worker_sf.js"] 30 | }, 31 | "options_ui": { 32 | "page": "options.html", 33 | "open_in_tab": true 34 | }, 35 | "content_scripts": [ 36 | { 37 | "matches": ["file:///*/*","*://*/*"], 38 | "js": ["lib/jquery-3.1.0.min.js", "lib/microdatajs/jquery.microdata.js", 39 | "lib/microdatajs/jquery.microdata.json.js", "lib/RDFa.js", "lib/n3-browser.js", 40 | "lib/jquery.mark.js", "lib/namespace.js", "lib/posh.js", "utils.js", "helpers_ui.js", 41 | "browser.js", "settings.js", "sniffer_nano.js", "super_links.js", 42 | "sniffer.js", "chat-inject.js", "social_sniffer.js"], 43 | "css": ["content.css"], 44 | "run_at": "document_idle" 45 | }, 46 | { 47 | "matches": ["https://openlinksoftware.github.io/*"], 48 | "js": ["browser.js", "lib/solid-client-authn.bundle.js", "oidc-webid-inject.js"], 49 | "run_at": "document_start" 50 | } 51 | ], 52 | "host_permissions": [ 53 | "" 54 | ], 55 | "permissions": [ 56 | "storage", 57 | "webNavigation", 58 | "contextMenus", 59 | "scripting", 60 | "declarativeNetRequest" 61 | ], 62 | 63 | "web_accessible_resources": [ 64 | "page_panel.html" 65 | ], 66 | 67 | "content_security_policy": { 68 | "extension_pages": "script-src 'self' ; object-src 'self' safari-web-extension://lib; style-src 'self' 'unsafe-inline' safari-web-extension://lib https://solid.openlinksw.com; media-src 'self' blob: https://* http://* 'unsafe-inline' safari-web-extension://lib ;" 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/oidc-webid-inject.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the OpenLink Structured Data Sniffer 3 | * 4 | * Copyright (C) 2015-2021 OpenLink Software 5 | * 6 | * This project is free software; you can redistribute it and/or modify it 7 | * under the terms of the GNU General Public License as published by the 8 | * Free Software Foundation; only version 2 of the License, dated June 1991. 9 | * 10 | * This program is distributed in the hope that it will be useful, but 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License along 16 | * with this program; if not, write to the Free Software Foundation, Inc., 17 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | * 19 | */ 20 | 21 | 22 | (function () { 23 | 24 | const prefix_code = "oidc-code:"; 25 | const prefix_code1 = "oidc-code1:"; 26 | 27 | window.addEventListener("message", recvMessage, false); 28 | 29 | async function recvMessage(event) 30 | { 31 | var ev_data; 32 | var session = null; 33 | var idp = null; 34 | 35 | const ev = String(event.data); 36 | if (!ev.startsWith(prefix_code) && !ev.startsWith(prefix_code1)) 37 | return; 38 | 39 | const authData = (ev.startsWith(prefix_code)) ? ev.substring(prefix_code.length) : ev.substring(prefix_code1.length); 40 | const auth = JSON.parse(atob(authData)); 41 | 42 | const callback_url = new URL(auth.url); 43 | if (callback_url.searchParams.get('app') !== 'osds') 44 | return; 45 | 46 | await save_data('oidc_code', authData); 47 | Browser.api.runtime.sendMessage({cmd:'store_updated', key:'oidc_code'}); 48 | 49 | setTimeout(function (){ 50 | if (ev.startsWith(prefix_code1)) 51 | Browser.api.runtime.sendMessage({cmd:'close_oidc_web_slogin', url: document.location.href}); 52 | else 53 | Browser.api.runtime.sendMessage({cmd:'close_oidc_web', url: document.location.href}); 54 | }, 1500); 55 | } 56 | 57 | 58 | async function save_data(key, val) 59 | { 60 | var rec = {}; 61 | rec[key]=val; 62 | if (Browser.is_chrome) { 63 | return new Promise(function (resolve, reject) { 64 | Browser.api.storage.local.set(rec, () => { 65 | resolve() 66 | }); 67 | }) 68 | } else { 69 | return Browser.api.storage.local.set(rec); 70 | } 71 | } 72 | 73 | 74 | })(); 75 | -------------------------------------------------------------------------------- /src/service_worker.js: -------------------------------------------------------------------------------- 1 | class wStore { 2 | constructor() 3 | { 4 | this.data = {}; 5 | this.keys = []; 6 | } 7 | 8 | sync() 9 | { 10 | this.keys = Object.keys(this.data); 11 | } 12 | 13 | key(idx) 14 | { 15 | if (idx < 0 || idx >= this.keys.length) 16 | return null; 17 | return this.keys[idx]; 18 | } 19 | 20 | setItem(key, val) 21 | { 22 | this.data[key] = val; 23 | this.sync(); 24 | } 25 | 26 | getItem(key) 27 | { 28 | return this.data[key]; 29 | } 30 | 31 | removeItem(key) 32 | { 33 | delete this.data[key]; 34 | this.sync(); 35 | } 36 | 37 | get length() 38 | { 39 | return this.keys.length; 40 | } 41 | 42 | } 43 | 44 | 45 | 46 | var window = {}; 47 | var localStorage = new wStore(); 48 | var gpt3encoder; 49 | 50 | window.localStorage = localStorage; 51 | 52 | 53 | try { 54 | 55 | importScripts( 56 | "./lib/gpt3-encoder.js", 57 | "./browser.js", 58 | "./settings.js", 59 | "./utils.js", 60 | "./helpers.js", 61 | "./lib/solid-client-authn.bundle.js", 62 | "./OidcWebid.js", 63 | "./chat-srv.js", 64 | "./background_web.js", 65 | "./background.js" 66 | ); 67 | 68 | gpt3encoder = window.gpt3encoder; 69 | 70 | //===================================== 71 | 72 | async function setUID() 73 | { 74 | const settings = new Settings(); 75 | const chk = await settings.getValue('ext.osds.pref.user.chk'); 76 | const pref_user = await settings.getValue('ext.osds.pref.user'); 77 | await setRule_OnBehalfOf(chk, pref_user); 78 | } 79 | 80 | Browser.api.runtime.onInstalled.addListener(async (details) => { 81 | if(details.reason !== "install" && details.reason !== "update") return; 82 | try { 83 | await setUID(); 84 | await Actions.clear(); 85 | await GVars.clear(); 86 | } catch(ex) { 87 | console.log(ex); 88 | } 89 | }); 90 | 91 | } catch(ex) { 92 | console.log(ex); 93 | } 94 | 95 | -------------------------------------------------------------------------------- /src/service_worker_ff.js: -------------------------------------------------------------------------------- 1 | try { 2 | 3 | async function setUID() 4 | { 5 | const settings = new Settings(); 6 | const chk = await settings.getValue('ext.osds.pref.user.chk'); 7 | const pref_user = await settings.getValue('ext.osds.pref.user'); 8 | await setRule_OnBehalfOf(chk, pref_user); 9 | } 10 | 11 | Browser.api.runtime.onInstalled.addListener(async (details) => { 12 | if(details.reason !== "install" && details.reason !== "update") return; 13 | try { 14 | await setUID(); 15 | await Actions.clear(); 16 | await GVars.clear(); 17 | } catch(ex) { 18 | console.log(ex); 19 | } 20 | }); 21 | 22 | } catch(ex) { 23 | console.log(ex); 24 | } 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/service_worker_sf.js: -------------------------------------------------------------------------------- 1 | try { 2 | 3 | async function setUID() 4 | { 5 | const settings = new Settings(); 6 | const chk = await settings.getValue('ext.osds.pref.user.chk'); 7 | const pref_user = await settings.getValue('ext.osds.pref.user'); 8 | await setRule_OnBehalfOf(chk, pref_user); 9 | } 10 | 11 | Browser.api.runtime.onInstalled.addListener(async (details) => { 12 | if(details.reason !== "install" && details.reason !== "update") return; 13 | console.log('===Update ext==='); 14 | try { 15 | //await setUID(); 16 | await Actions.clear(); 17 | await GVars.clear(); 18 | } catch(ex) { 19 | console.log(ex); 20 | } 21 | }); 22 | 23 | } catch(ex) { 24 | console.log(ex); 25 | } 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/tabs.css: -------------------------------------------------------------------------------- 1 | 2 | .tabs { 3 | float: none; 4 | list-style: none; 5 | position: relative; 6 | text-align: left; 7 | padding: 0 0 0.3em 0; 8 | margin-top: -5px; 9 | } 10 | 11 | .tabs li { 12 | float: left; 13 | display: block; 14 | margin-right: 3px; 15 | } 16 | 17 | 18 | .tabs input[type="radio"] { 19 | position: absolute; 20 | top: 0; 21 | left: -9999px; 22 | } 23 | 24 | .tabs label { 25 | display: block; 26 | padding: 4px 4px 6px 4px; 27 | border-radius: 4px 4px 0 0; 28 | font-size: 13px; 29 | font-weight: normal; 30 | background: lightgray; 31 | cursor: pointer; 32 | position: relative; 33 | top: 4px; 34 | -moz-transition: all 0.1s ease-in-out; 35 | -o-transition: all 0.1s ease-in-out; 36 | -webkit-transition: all 0.1s ease-in-out; 37 | transition: all 0.1s ease-in-out; 38 | } 39 | 40 | .tabs label:hover { 41 | background: lightgray; 42 | } 43 | 44 | .tabs .tab-content { 45 | z-index: 2; 46 | display: none; 47 | overflow: auto; 48 | width: calc(100% - 5px); 49 | height: calc(100vh - 70px); 50 | position: absolute; 51 | top: 33px; 52 | left: 0; 53 | border: 1px solid #c9c3ba; 54 | font-size: 13px; 55 | } 56 | 57 | .tabs [id^="itab"]:checked + label { 58 | top: 0; 59 | padding: 9px 4px 6px 4px; 60 | background: #f1f0ee; 61 | color: blue; 62 | font-weight: bold; 63 | border: 1px solid #c9c3ba; 64 | } 65 | 66 | .tabs [id^="itab"]:checked ~ [role^="tabpanel"] { 67 | display: block; 68 | } 69 | --------------------------------------------------------------------------------