├── .gitignore ├── media ├── icon.png └── preview.gif ├── .vscode ├── extensions.json └── launch.json ├── .vscodeignore ├── .eslintrc ├── .github └── workflows │ ├── nodejs.yml │ ├── release-ovsx.yml │ └── release-vsce.yml ├── README.md ├── src ├── steps │ ├── pickVersion.js │ ├── pickPackage.js │ ├── pickFormat.js │ └── pickFile.js ├── extension.js └── multiStepInput.js ├── package.json └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vscode-test/ 3 | node_modules/ 4 | *.vsix 5 | -------------------------------------------------------------------------------- /media/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jsdelivr/plugin-vs-code/HEAD/media/icon.png -------------------------------------------------------------------------------- /media/preview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jsdelivr/plugin-vs-code/HEAD/media/preview.gif -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "dbaeumer.vscode-eslint" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .idea/** 2 | .github/** 3 | .vscode/** 4 | .vscode-test/** 5 | test/** 6 | .gitignore 7 | vsc-extension-quickstart.md 8 | **/jsconfig.json 9 | **/*.map 10 | **/.eslintrc.json 11 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@martin-kolarik/eslint-config", 3 | "globals": { 4 | "atom": true 5 | }, 6 | "rules": { 7 | "node/no-missing-require": [ 8 | "error", 9 | { 10 | "allowModules": [ 11 | "vscode" 12 | ] 13 | } 14 | ] 15 | }, 16 | "plugins": [ 17 | "html" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "configurations": [ 4 | { 5 | "name": "Extension", 6 | "type": "extensionHost", 7 | "request": "launch", 8 | "runtimeExecutable": "${execPath}", 9 | "args": [ 10 | "--extensionDevelopmentPath=${workspaceFolder}" 11 | ] 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /.github/workflows/nodejs.yml: -------------------------------------------------------------------------------- 1 | name: Node CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | strategy: 9 | matrix: 10 | node-version: [14.x] 11 | 12 | steps: 13 | - uses: actions/checkout@v2 14 | 15 | - name: Use Node.js ${{ matrix.node-version }} 16 | uses: actions/setup-node@v2 17 | with: 18 | node-version: ${{ matrix.node-version }} 19 | 20 | - name: npm install, and test 21 | run: | 22 | npm ci 23 | npm test 24 | env: 25 | CI: true 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # plugin-vs-code 2 | 3 | Quickly insert any npm package from [jsDelivr CDN](https://www.jsdelivr.com). 4 | 5 | Launch command "Add jsDelivr package" from command palette. 6 | 7 | ![Screenshot 1](media/preview.gif) 8 | 9 | ## Installation 10 | 11 | In your IDE, go to `File -> Preferences -> Extensions` and search for `jsDelivr`. 12 | 13 | ## Features 14 | 15 | - Insert just the URL, HTML code, or HTML + SRI. 16 | - Offers [minified versions](https://www.jsdelivr.com/features#minify) of all CSS/JS files. 17 | 18 | ## Setup for development 19 | 20 | 1. Fork the repository 21 | 2. In Visual Studio Code IDE open new terminal and run `npm install` 22 | 3. Press F5 to run 23 | -------------------------------------------------------------------------------- /.github/workflows/release-ovsx.yml: -------------------------------------------------------------------------------- 1 | name: Release / OVSX 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | 8 | jobs: 9 | release: 10 | runs-on: ubuntu-latest 11 | strategy: 12 | matrix: 13 | node-version: [14.x] 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | 18 | - name: Use Node.js ${{ matrix.node-version }} 19 | uses: actions/setup-node@v2 20 | with: 21 | node-version: ${{ matrix.node-version }} 22 | 23 | - name: npm install, and test 24 | run: | 25 | npm ci 26 | npm test 27 | env: 28 | CI: true 29 | 30 | - name: Publish to OVSX 31 | run: npx ovsx publish -p ${{ secrets.OVSX_TOKEN }} 32 | -------------------------------------------------------------------------------- /.github/workflows/release-vsce.yml: -------------------------------------------------------------------------------- 1 | name: Release / VSCE 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | 8 | jobs: 9 | release: 10 | runs-on: ubuntu-latest 11 | strategy: 12 | matrix: 13 | node-version: [14.x] 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | 18 | - name: Use Node.js ${{ matrix.node-version }} 19 | uses: actions/setup-node@v2 20 | with: 21 | node-version: ${{ matrix.node-version }} 22 | 23 | - name: npm install, and test 24 | run: | 25 | npm ci 26 | npm test 27 | env: 28 | CI: true 29 | 30 | - name: Publish to VSCE 31 | run: npx vsce publish -p ${{ secrets.VSCE_TOKEN }} 32 | -------------------------------------------------------------------------------- /src/steps/pickVersion.js: -------------------------------------------------------------------------------- 1 | const pickFile = require('./pickFile').pickFile; 2 | const semver = require('semver'); 3 | 4 | async function pickVersion (input, state) { 5 | Object.keys(state.pkg.versions).forEach((version) => { 6 | if (!semver.valid(version)) { 7 | delete state.pkg.versions[version]; 8 | } 9 | }); 10 | 11 | let versions = semver.rsort(Object.keys(state.pkg.versions)); 12 | 13 | const pick = await input.showQuickPick({ 14 | title: 'Pick version', 15 | step: 2, 16 | totalSteps: 4, 17 | placeholder: 'Pick version', 18 | items: versions.map((version) => { 19 | return { label: version }; 20 | }), 21 | }); 22 | 23 | state.version = pick.label; 24 | return input => pickFile(input, state); 25 | } 26 | 27 | exports.pickVersion = pickVersion; 28 | -------------------------------------------------------------------------------- /src/extension.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | const MultiStepInput = require('./multiStepInput').MultiStepInput; 3 | const pickPackage = require('./steps/pickPackage').pickPackage; 4 | 5 | function activate (context) { 6 | async function collectInputs () { 7 | const state = {}; 8 | await MultiStepInput.run(input => pickPackage(input, state)); 9 | return state; 10 | } 11 | 12 | let disposable = vscode.commands.registerCommand('jsDelivr.addPkg', () => { 13 | if (vscode.window.activeTextEditor === undefined) { 14 | vscode.window.showErrorMessage('JsDelivr plugin requires a text editor to be open.'); 15 | return; 16 | } 17 | 18 | collectInputs(); 19 | }); 20 | 21 | context.subscriptions.push(disposable); 22 | } 23 | 24 | exports.activate = activate; 25 | 26 | function deactivate () {} 27 | 28 | module.exports = { 29 | activate, 30 | deactivate, 31 | }; 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsdelivr", 3 | "displayName": "jsDelivr", 4 | "description": "Quickly insert any npm package from jsDelivr CDN.", 5 | "version": "1.0.2", 6 | "license": "OSL-3.0", 7 | "publisher": "jsDelivr", 8 | "icon": "media/icon.png", 9 | "engines": { 10 | "vscode": "^1.33.0" 11 | }, 12 | "categories": [ 13 | "Other" 14 | ], 15 | "activationEvents": [ 16 | "onCommand:jsDelivr.addPkg" 17 | ], 18 | "main": "./src/extension.js", 19 | "contributes": { 20 | "commands": [ 21 | { 22 | "command": "jsDelivr.addPkg", 23 | "title": "jsDelivr: Add jsDelivr package" 24 | } 25 | ] 26 | }, 27 | "scripts": { 28 | "lint": "eslint src", 29 | "postinstall": "node ./node_modules/vscode/bin/install", 30 | "test": "npm run lint" 31 | }, 32 | "dependencies": { 33 | "algoliasearch": "^3.35.1", 34 | "got": "^9.6.0", 35 | "semver": "^6.3.0" 36 | }, 37 | "devDependencies": { 38 | "@martin-kolarik/eslint-config": "^2.0.1", 39 | "eslint": "^6.8.0", 40 | "eslint-plugin-chai-expect": "^2.1.0", 41 | "eslint-plugin-html": "^6.0.2", 42 | "eslint-plugin-node": "^9.2.0", 43 | "eslint-plugin-promise": "^4.2.1", 44 | "vscode": "^1.1.37" 45 | }, 46 | "repository": { 47 | "type": "git", 48 | "url": "https://github.com/jsdelivr/plugin-vs-code.git" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/steps/pickPackage.js: -------------------------------------------------------------------------------- 1 | const algoliasearch = require('algoliasearch'); 2 | const pickVersion = require('./pickVersion').pickVersion; 3 | const InputFlowAction = require('../multiStepInput').InputFlowAction; 4 | const vscode = require('vscode'); 5 | 6 | const appId = 'OFCNCOG2CU'; 7 | const apiKey = 'f54e21fa3a2a0160595bb058179bfb1e'; 8 | const indexName = 'npm-search'; 9 | 10 | async function pickPackage (input, state) { 11 | let client = algoliasearch(appId, apiKey); 12 | let index = client.initIndex(indexName); 13 | 14 | let response; 15 | 16 | try { 17 | response = await index.search(''); 18 | } catch (e) { 19 | vscode.window.showErrorMessage('Unexpected error occurred'); 20 | return InputFlowAction.cancel; 21 | } 22 | 23 | const pick = await input.showQuickPick({ 24 | title: 'Pick package', 25 | step: 1, 26 | totalSteps: 4, 27 | placeholder: 'Pick package', 28 | items: response.hits.map((hit) => { 29 | return { label: hit.name }; 30 | }), 31 | onChangeValue: async (value, input) => { 32 | input.items = []; 33 | 34 | try { 35 | response = await index.search(value); 36 | } catch (e) { 37 | vscode.window.showErrorMessage('Unexpected error occurred'); 38 | return; 39 | } 40 | 41 | if (value === input.value) { 42 | input.items = response.hits.map((hit) => { 43 | return { label: hit.name }; 44 | }); 45 | } 46 | }, 47 | }); 48 | 49 | let findPkg = function (pkg) { 50 | return pkg.name === pick.label; 51 | }; 52 | 53 | state.pkg = response.hits.find(findPkg); 54 | return input => pickVersion(input, state); 55 | } 56 | 57 | exports.pickPackage = pickPackage; 58 | -------------------------------------------------------------------------------- /src/steps/pickFormat.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | 3 | const jsDelivrUrl = 'https://cdn.jsdelivr.net/npm/'; 4 | 5 | let insertText = function (text) { 6 | let editor = vscode.window.activeTextEditor; 7 | 8 | if (editor === undefined) { 9 | vscode.window.showErrorMessage('JsDelivr plugin requires a text editor to be open.'); 10 | return; 11 | } 12 | 13 | editor.edit(edit => editor.selections.forEach((selection) => { 14 | edit.delete(selection); 15 | edit.insert(selection.start, text); 16 | })); 17 | }; 18 | 19 | async function pickFormat (input, state) { 20 | let options = [ 'Insert URL', 'Insert HTML' ]; 21 | 22 | if (!state.isGenMin) { 23 | options.push('Insert HTML + SRI'); 24 | } 25 | 26 | const pick = await input.showQuickPick({ 27 | title: 'Pick insert format', 28 | step: 4, 29 | totalSteps: 4, 30 | placeholder: 'Pick insert format', 31 | items: options.map((option) => { 32 | return { label: option }; 33 | }), 34 | }); 35 | 36 | let url = `${jsDelivrUrl}${state.pkg.name}@${state.version}/${state.file}`; 37 | 38 | if (pick.label === options[0]) { 39 | insertText(url); 40 | } else if (pick.label === options[1]) { 41 | if (state.file.endsWith('.js')) { 42 | insertText(``); 43 | } else { 44 | insertText(``); 45 | } 46 | } else if (pick.label === 'Insert HTML + SRI') { 47 | if (state.file.endsWith('.js')) { 48 | insertText(``); 49 | } else { 50 | insertText(``); 51 | } 52 | } 53 | } 54 | 55 | exports.pickFormat = pickFormat; 56 | -------------------------------------------------------------------------------- /src/multiStepInput.js: -------------------------------------------------------------------------------- 1 | const vscode = require('vscode'); 2 | 3 | class InputFlowAction { 4 | 5 | } 6 | 7 | InputFlowAction.back = new InputFlowAction(); 8 | InputFlowAction.cancel = new InputFlowAction(); 9 | InputFlowAction.resume = new InputFlowAction(); 10 | 11 | exports.InputFlowAction = InputFlowAction; 12 | 13 | class MultiStepInput { 14 | constructor () { 15 | this.steps = []; 16 | } 17 | 18 | static async run (start) { 19 | const input = new MultiStepInput(); 20 | return input.stepThrough(start); 21 | } 22 | 23 | async stepThrough (start) { 24 | let step = start; 25 | 26 | while (step) { 27 | this.steps.push(step); 28 | if (this.current) { 29 | this.current.enabled = false; 30 | this.current.busy = true; 31 | } 32 | 33 | try { 34 | step = await step(this); 35 | } catch (err) { 36 | if (err === InputFlowAction.back) { 37 | this.steps.pop(); 38 | step = this.steps.pop(); 39 | } else if (err === InputFlowAction.resume) { 40 | step = this.steps.pop(); 41 | } else if (err === InputFlowAction.cancel) { 42 | step = undefined; 43 | } else { 44 | throw err; 45 | } 46 | } 47 | } 48 | 49 | if (this.current) { 50 | this.current.dispose(); 51 | } 52 | } 53 | 54 | async showQuickPick ({ title, step, totalSteps, items, activeItem, placeholder, buttons, onChangeValue }) { 55 | const disposables = []; 56 | 57 | try { 58 | return await new Promise((resolve, reject) => { 59 | const input = vscode.window.createQuickPick(); 60 | 61 | input.title = title; 62 | input.step = step; 63 | input.totalSteps = totalSteps; 64 | input.placeholder = placeholder; 65 | input.items = items; 66 | if (activeItem) { 67 | input.activeItems = [ activeItem ]; 68 | } 69 | 70 | input.buttons = [ 71 | ...this.steps.length > 1 ? [ vscode.QuickInputButtons.Back ] : [], 72 | ...buttons || [], 73 | ]; 74 | disposables.push( 75 | input.onDidTriggerButton((item) => { 76 | if (item === vscode.QuickInputButtons.Back) { 77 | reject(InputFlowAction.back); 78 | } else { 79 | resolve(item); 80 | } 81 | }), 82 | input.onDidChangeSelection(items => resolve(items[0])), 83 | input.onDidChangeValue(() => { 84 | if (onChangeValue) { 85 | onChangeValue(input.value, input); 86 | } 87 | }) 88 | ); 89 | if (this.current) { 90 | this.current.dispose(); 91 | } 92 | 93 | this.current = input; 94 | this.current.show(); 95 | }); 96 | } finally { 97 | disposables.forEach(d => d.dispose()); 98 | } 99 | } 100 | } 101 | 102 | exports.MultiStepInput = MultiStepInput; 103 | -------------------------------------------------------------------------------- /src/steps/pickFile.js: -------------------------------------------------------------------------------- 1 | const got = require('got'); 2 | const vscode = require('vscode'); 3 | const pickFormat = require('./pickFormat').pickFormat; 4 | const InputFlowAction = require('../multiStepInput').InputFlowAction; 5 | 6 | const extensionId = 'jsdelivr'; 7 | const extensionPublisher = 'jsDelivr'; 8 | 9 | const jsDelivrEndpoint = 'https://data.jsdelivr.com/v1/package/npm/'; 10 | const userAgent = `jsDelivr Visual Studio Code plugin/${vscode.extensions.getExtension(`${extensionPublisher}.${extensionId}`).packageJSON.version}`; 11 | 12 | async function pickFile (input, state) { 13 | let response; 14 | let minFiles = []; 15 | let hashes = new Map(); 16 | 17 | try { 18 | response = await got(`${state.pkg.name}@${state.version}/flat`, { 19 | baseUrl: jsDelivrEndpoint, 20 | headers: { 21 | 'user-agent': userAgent, 22 | }, 23 | }); 24 | } catch (e) { 25 | vscode.window.showErrorMessage('Unexpected error occurred'); 26 | return InputFlowAction.cancel; 27 | } 28 | 29 | const body = JSON.parse(response.body); 30 | const defaultFile = body.default.substr(1); // remove leading `/` 31 | 32 | body.files.forEach((file) => { 33 | hashes.set(file.name.substr(1), file.hash); 34 | }); 35 | 36 | let files = body.files.filter((file) => { 37 | // we only want .js and .css files 38 | return file.name.toLowerCase().endsWith('.js') || file.name.toLowerCase().endsWith('.css'); 39 | }).map((file) => { 40 | return file.name.substr(1); // remove leading `/` 41 | }); 42 | 43 | files.forEach((file) => { 44 | // not ending with neither `.min.js` or `.min.css` 45 | if (!file.toLowerCase().endsWith('.min.js') && !file.toLowerCase().endsWith('.min.css')) { 46 | // rename to `.min.js` or `.min.css` 47 | minFiles.push(file.toLowerCase().endsWith('.js') ? file.replace(/\.js$/i, '.min.js') : file.replace(/\.css$/i, '.min.css')); 48 | } 49 | }); 50 | 51 | let completeFileList = files.concat(minFiles) 52 | .filter((v, i, a) => a.indexOf(v) === i) // no duplicates! 53 | .sort((file1, file2) => { 54 | return file1 > file2 ? 1 : -1; // sort alphabetically (https://stackoverflow.com/a/7087833/2465955) 55 | }); 56 | 57 | // delete the default file, then add it back to index 0 58 | completeFileList.splice(completeFileList.indexOf(defaultFile), 1); 59 | completeFileList.unshift(defaultFile); 60 | 61 | const pick = await input.showQuickPick({ 62 | title: 'Pick file', 63 | step: 3, 64 | totalSteps: 4, 65 | placeholder: 'Pick file', 66 | items: completeFileList.map((file) => { 67 | return { label: file }; 68 | }), 69 | }); 70 | 71 | state.file = pick.label; 72 | 73 | if (files.includes(pick.label)) { 74 | state.hash = hashes.get(pick.label); 75 | state.isGenMin = false; 76 | } else { 77 | state.isGenMin = true; 78 | } 79 | 80 | return input => pickFormat(input, state); 81 | } 82 | 83 | exports.pickFile = pickFile; 84 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Open Software License ("OSL") v. 3.0 2 | 3 | This Open Software License (the "License") applies to any original work of 4 | authorship (the "Original Work") whose owner (the "Licensor") has placed the 5 | following licensing notice adjacent to the copyright notice for the Original 6 | Work: 7 | 8 | Licensed under the Open Software License version 3.0 9 | 10 | 1) Grant of Copyright License. Licensor grants You a worldwide, royalty-free, 11 | non-exclusive, sublicensable license, for the duration of the copyright, to do 12 | the following: 13 | 14 | a) to reproduce the Original Work in copies, either alone or as part of a 15 | collective work; 16 | 17 | b) to translate, adapt, alter, transform, modify, or arrange the Original 18 | Work, thereby creating derivative works ("Derivative Works") based upon the 19 | Original Work; 20 | 21 | c) to distribute or communicate copies of the Original Work and Derivative 22 | Works to the public, with the proviso that copies of Original Work or 23 | Derivative Works that You distribute or communicate shall be licensed under 24 | this Open Software License; 25 | 26 | d) to perform the Original Work publicly; and 27 | 28 | e) to display the Original Work publicly. 29 | 30 | 2) Grant of Patent License. Licensor grants You a worldwide, royalty-free, 31 | non-exclusive, sublicensable license, under patent claims owned or controlled 32 | by the Licensor that are embodied in the Original Work as furnished by the 33 | Licensor, for the duration of the patents, to make, use, sell, offer for sale, 34 | have made, and import the Original Work and Derivative Works. 35 | 36 | 3) Grant of Source Code License. The term "Source Code" means the preferred 37 | form of the Original Work for making modifications to it and all available 38 | documentation describing how to modify the Original Work. Licensor agrees to 39 | provide a machine-readable copy of the Source Code of the Original Work along 40 | with each copy of the Original Work that Licensor distributes. Licensor 41 | reserves the right to satisfy this obligation by placing a machine-readable 42 | copy of the Source Code in an information repository reasonably calculated to 43 | permit inexpensive and convenient access by You for as long as Licensor 44 | continues to distribute the Original Work. 45 | 46 | 4) Exclusions From License Grant. Neither the names of Licensor, nor the names 47 | of any contributors to the Original Work, nor any of their trademarks or 48 | service marks, may be used to endorse or promote products derived from this 49 | Original Work without express prior permission of the Licensor. Except as 50 | expressly stated herein, nothing in this License grants any license to 51 | Licensor's trademarks, copyrights, patents, trade secrets or any other 52 | intellectual property. No patent license is granted to make, use, sell, offer 53 | for sale, have made, or import embodiments of any patent claims other than the 54 | licensed claims defined in Section 2. No license is granted to the trademarks 55 | of Licensor even if such marks are included in the Original Work. Nothing in 56 | this License shall be interpreted to prohibit Licensor from licensing under 57 | terms different from this License any Original Work that Licensor otherwise 58 | would have a right to license. 59 | 60 | 5) External Deployment. The term "External Deployment" means the use, 61 | distribution, or communication of the Original Work or Derivative Works in any 62 | way such that the Original Work or Derivative Works may be used by anyone 63 | other than You, whether those works are distributed or communicated to those 64 | persons or made available as an application intended for use over a network. 65 | As an express condition for the grants of license hereunder, You must treat 66 | any External Deployment by You of the Original Work or a Derivative Work as a 67 | distribution under section 1(c). 68 | 69 | 6) Attribution Rights. You must retain, in the Source Code of any Derivative 70 | Works that You create, all copyright, patent, or trademark notices from the 71 | Source Code of the Original Work, as well as any notices of licensing and any 72 | descriptive text identified therein as an "Attribution Notice." You must cause 73 | the Source Code for any Derivative Works that You create to carry a prominent 74 | Attribution Notice reasonably calculated to inform recipients that You have 75 | modified the Original Work. 76 | 77 | 7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that 78 | the copyright in and to the Original Work and the patent rights granted herein 79 | by Licensor are owned by the Licensor or are sublicensed to You under the 80 | terms of this License with the permission of the contributor(s) of those 81 | copyrights and patent rights. Except as expressly stated in the immediately 82 | preceding sentence, the Original Work is provided under this License on an "AS 83 | IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without 84 | limitation, the warranties of non-infringement, merchantability or fitness for 85 | a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK 86 | IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this 87 | License. No license to the Original Work is granted by this License except 88 | under this disclaimer. 89 | 90 | 8) Limitation of Liability. Under no circumstances and under no legal theory, 91 | whether in tort (including negligence), contract, or otherwise, shall the 92 | Licensor be liable to anyone for any indirect, special, incidental, or 93 | consequential damages of any character arising as a result of this License or 94 | the use of the Original Work including, without limitation, damages for loss 95 | of goodwill, work stoppage, computer failure or malfunction, or any and all 96 | other commercial damages or losses. This limitation of liability shall not 97 | apply to the extent applicable law prohibits such limitation. 98 | 99 | 9) Acceptance and Termination. If, at any time, You expressly assented to this 100 | License, that assent indicates your clear and irrevocable acceptance of this 101 | License and all of its terms and conditions. If You distribute or communicate 102 | copies of the Original Work or a Derivative Work, You must make a reasonable 103 | effort under the circumstances to obtain the express assent of recipients to 104 | the terms of this License. This License conditions your rights to undertake 105 | the activities listed in Section 1, including your right to create Derivative 106 | Works based upon the Original Work, and doing so without honoring these terms 107 | and conditions is prohibited by copyright law and international treaty. 108 | Nothing in this License is intended to affect copyright exceptions and 109 | limitations (including "fair use" or "fair dealing"). This License shall 110 | terminate immediately and You may no longer exercise any of the rights granted 111 | to You by this License upon your failure to honor the conditions in Section 112 | 1(c). 113 | 114 | 10) Termination for Patent Action. This License shall terminate automatically 115 | and You may no longer exercise any of the rights granted to You by this 116 | License as of the date You commence an action, including a cross-claim or 117 | counterclaim, against Licensor or any licensee alleging that the Original Work 118 | infringes a patent. This termination provision shall not apply for an action 119 | alleging patent infringement by combinations of the Original Work with other 120 | software or hardware. 121 | 122 | 11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this 123 | License may be brought only in the courts of a jurisdiction wherein the 124 | Licensor resides or in which Licensor conducts its primary business, and under 125 | the laws of that jurisdiction excluding its conflict-of-law provisions. The 126 | application of the United Nations Convention on Contracts for the 127 | International Sale of Goods is expressly excluded. Any use of the Original 128 | Work outside the scope of this License or after its termination shall be 129 | subject to the requirements and penalties of copyright or patent law in the 130 | appropriate jurisdiction. This section shall survive the termination of this 131 | License. 132 | 133 | 12) Attorneys' Fees. In any action to enforce the terms of this License or 134 | seeking damages relating thereto, the prevailing party shall be entitled to 135 | recover its costs and expenses, including, without limitation, reasonable 136 | attorneys' fees and costs incurred in connection with such action, including 137 | any appeal of such action. This section shall survive the termination of this 138 | License. 139 | 140 | 13) Miscellaneous. If any provision of this License is held to be 141 | unenforceable, such provision shall be reformed only to the extent necessary 142 | to make it enforceable. 143 | 144 | 14) Definition of "You" in This License. "You" throughout this License, 145 | whether in upper or lower case, means an individual or a legal entity 146 | exercising rights under, and complying with all of the terms of, this License. 147 | For legal entities, "You" includes any entity that controls, is controlled by, 148 | or is under common control with you. For purposes of this definition, 149 | "control" means (i) the power, direct or indirect, to cause the direction or 150 | management of such entity, whether by contract or otherwise, or (ii) ownership 151 | of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial 152 | ownership of such entity. 153 | 154 | 15) Right to Use. You may use the Original Work in all ways not otherwise 155 | restricted or conditioned by this License or by law, and Licensor promises not 156 | to interfere with or be responsible for such uses by You. 157 | 158 | 16) Modification of This License. This License is Copyright © 2005 Lawrence 159 | Rosen. Permission is granted to copy, distribute, or communicate this License 160 | without modification. Nothing in this License permits You to modify this 161 | License as applied to the Original Work or to Derivative Works. However, You 162 | may modify the text of this License and copy, distribute or communicate your 163 | modified version (the "Modified License") and apply it to other original works 164 | of authorship subject to the following conditions: (i) You may not indicate in 165 | any way that your Modified License is the "Open Software License" or "OSL" and 166 | you may not use those names in the name of your Modified License; (ii) You 167 | must replace the notice specified in the first paragraph above with the notice 168 | "Licensed under " or with a notice of your own 169 | that is not confusingly similar to the notice in this License; and (iii) You 170 | may not claim that your original works are open source software unless your 171 | Modified License has been approved by Open Source Initiative (OSI) and You 172 | comply with its license review and certification process. 173 | --------------------------------------------------------------------------------