├── .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 | 
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 |
--------------------------------------------------------------------------------