зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1208257 - [webext] browser_action.json (r=kmag)
This commit is contained in:
Родитель
4bcec16ec8
Коммит
a3d3a41850
|
@ -200,7 +200,7 @@ extensions.on("shutdown", (type, extension) => {
|
|||
});
|
||||
/* eslint-enable mozilla/balanced-listeners */
|
||||
|
||||
extensions.registerAPI((extension, context) => {
|
||||
extensions.registerSchemaAPI("browserAction", null, (extension, context) => {
|
||||
return {
|
||||
browserAction: {
|
||||
onClicked: new EventManager(context, "browserAction.onClicked", fire => {
|
||||
|
@ -215,45 +215,45 @@ extensions.registerAPI((extension, context) => {
|
|||
}).api(),
|
||||
|
||||
enable: function(tabId) {
|
||||
let tab = tabId ? TabManager.getTab(tabId) : null;
|
||||
let tab = tabId !== null ? TabManager.getTab(tabId) : null;
|
||||
browserActionOf(extension).setProperty(tab, "enabled", true);
|
||||
},
|
||||
|
||||
disable: function(tabId) {
|
||||
let tab = tabId ? TabManager.getTab(tabId) : null;
|
||||
let tab = tabId !== null ? TabManager.getTab(tabId) : null;
|
||||
browserActionOf(extension).setProperty(tab, "enabled", false);
|
||||
},
|
||||
|
||||
setTitle: function(details) {
|
||||
let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
|
||||
let tab = details.tabId !== null ? TabManager.getTab(details.tabId) : null;
|
||||
browserActionOf(extension).setProperty(tab, "title", details.title);
|
||||
},
|
||||
|
||||
getTitle: function(details, callback) {
|
||||
let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
|
||||
let tab = details.tabId !== null ? TabManager.getTab(details.tabId) : null;
|
||||
let title = browserActionOf(extension).getProperty(tab, "title");
|
||||
runSafe(context, callback, title);
|
||||
},
|
||||
|
||||
setIcon: function(details, callback) {
|
||||
let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
|
||||
let tab = details.tabId !== null ? TabManager.getTab(details.tabId) : null;
|
||||
let icon = IconDetails.normalize(details, extension, context);
|
||||
browserActionOf(extension).setProperty(tab, "icon", icon);
|
||||
},
|
||||
|
||||
setBadgeText: function(details) {
|
||||
let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
|
||||
let tab = details.tabId !== null ? TabManager.getTab(details.tabId) : null;
|
||||
browserActionOf(extension).setProperty(tab, "badgeText", details.text);
|
||||
},
|
||||
|
||||
getBadgeText: function(details, callback) {
|
||||
let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
|
||||
let tab = details.tabId !== null ? TabManager.getTab(details.tabId) : null;
|
||||
let text = browserActionOf(extension).getProperty(tab, "badgeText");
|
||||
runSafe(context, callback, text);
|
||||
},
|
||||
|
||||
setPopup: function(details) {
|
||||
let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
|
||||
let tab = details.tabId !== null ? TabManager.getTab(details.tabId) : null;
|
||||
// Note: Chrome resolves arguments to setIcon relative to the calling
|
||||
// context, but resolves arguments to setPopup relative to the extension
|
||||
// root.
|
||||
|
@ -264,18 +264,18 @@ extensions.registerAPI((extension, context) => {
|
|||
},
|
||||
|
||||
getPopup: function(details, callback) {
|
||||
let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
|
||||
let tab = details.tabId !== null ? TabManager.getTab(details.tabId) : null;
|
||||
let popup = browserActionOf(extension).getProperty(tab, "popup");
|
||||
runSafe(context, callback, popup);
|
||||
},
|
||||
|
||||
setBadgeBackgroundColor: function(details) {
|
||||
let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
|
||||
let tab = details.tabId !== null ? TabManager.getTab(details.tabId) : null;
|
||||
browserActionOf(extension).setProperty(tab, "badgeBackgroundColor", details.color);
|
||||
},
|
||||
|
||||
getBadgeBackgroundColor: function(details, callback) {
|
||||
let tab = details.tabId ? TabManager.getTab(details.tabId) : null;
|
||||
let tab = details.tabId !== null ? TabManager.getTab(details.tabId) : null;
|
||||
let color = browserActionOf(extension).getProperty(tab, "badgeBackgroundColor");
|
||||
runSafe(context, callback, color);
|
||||
},
|
||||
|
|
|
@ -12,6 +12,7 @@ const INTEGER = /^[1-9]\d*$/;
|
|||
|
||||
var {
|
||||
EventManager,
|
||||
instanceOf,
|
||||
} = ExtensionUtils;
|
||||
|
||||
// This file provides some useful code for the |tabs| and |windows|
|
||||
|
@ -38,7 +39,13 @@ global.IconDetails = {
|
|||
if (details.imageData) {
|
||||
let imageData = details.imageData;
|
||||
|
||||
if (imageData instanceof Cu.getGlobalForObject(imageData).ImageData) {
|
||||
// The global might actually be from Schema.jsm, which
|
||||
// normalizes most of our arguments. In that case it won't have
|
||||
// an ImageData property. But Schema.jsm doesn't normalize
|
||||
// actual ImageData objects, so they will come from a global
|
||||
// with the right property.
|
||||
let global = Cu.getGlobalForObject(imageData);
|
||||
if (instanceOf(imageData, "ImageData")) {
|
||||
imageData = {"19": imageData};
|
||||
}
|
||||
|
||||
|
@ -46,7 +53,6 @@ global.IconDetails = {
|
|||
if (!INTEGER.test(size)) {
|
||||
throw new Error(`Invalid icon size ${size}, must be an integer`);
|
||||
}
|
||||
|
||||
result[size] = this.convertImageDataToPNG(imageData[size], context);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,6 @@
|
|||
{
|
||||
"id": "CreateDetails",
|
||||
"description": "Object passed to the create() function.",
|
||||
"inline_doc": true,
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"parentId": {
|
||||
|
|
|
@ -0,0 +1,344 @@
|
|||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
[
|
||||
{
|
||||
"namespace": "browserAction",
|
||||
"description": "Use browser actions to put icons in the main browser toolbar, to the right of the address bar. In addition to its icon, a browser action can also have a tooltip, a badge, and a popup.",
|
||||
"types": [
|
||||
{
|
||||
"id": "ColorArray",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 255
|
||||
},
|
||||
"minItems": 4,
|
||||
"maxItems": 4
|
||||
},
|
||||
{
|
||||
"id": "ImageDataType",
|
||||
"type": "object",
|
||||
"isInstanceOf": "ImageData",
|
||||
"additionalProperties": { "type": "any" },
|
||||
"description": "Pixel data for an image. Must be an ImageData object (for example, from a <code>canvas</code> element)."
|
||||
}
|
||||
],
|
||||
"functions": [
|
||||
{
|
||||
"name": "setTitle",
|
||||
"type": "function",
|
||||
"description": "Sets the title of the browser action. This shows up in the tooltip.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "details",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"title": {
|
||||
"type": "string",
|
||||
"description": "The string the browser action should display when moused over."
|
||||
},
|
||||
"tabId": {
|
||||
"type": "integer",
|
||||
"optional": true,
|
||||
"description": "Limits the change to when a particular tab is selected. Automatically resets when the tab is closed."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getTitle",
|
||||
"type": "function",
|
||||
"description": "Gets the title of the browser action.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "details",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"tabId": {
|
||||
"type": "integer",
|
||||
"optional": true,
|
||||
"description": "Specify the tab to get the title from. If no tab is specified, the non-tab-specific title is returned."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "callback",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "result",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "setIcon",
|
||||
"type": "function",
|
||||
"description": "Sets the icon for the browser action. The icon can be specified either as the path to an image file or as the pixel data from a canvas element, or as dictionary of either one of those. Either the <b>path</b> or the <b>imageData</b> property must be specified.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "details",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"imageData": {
|
||||
"choices": [
|
||||
{ "$ref": "ImageDataType" },
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": {"$ref": "ImageDataType"}
|
||||
}
|
||||
],
|
||||
"optional": true,
|
||||
"description": "Either an ImageData object or a dictionary {size -> ImageData} representing icon to be set. If the icon is specified as a dictionary, the actual image to be used is chosen depending on screen's pixel density. If the number of image pixels that fit into one screen space unit equals <code>scale</code>, then image with size <code>scale</code> * 19 will be selected. Initially only scales 1 and 2 will be supported. At least one image must be specified. Note that 'details.imageData = foo' is equivalent to 'details.imageData = {'19': foo}'"
|
||||
},
|
||||
"path": {
|
||||
"choices": [
|
||||
{ "type": "string" },
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": {"type": "string"}
|
||||
}
|
||||
],
|
||||
"optional": true,
|
||||
"description": "Either a relative image path or a dictionary {size -> relative image path} pointing to icon to be set. If the icon is specified as a dictionary, the actual image to be used is chosen depending on screen's pixel density. If the number of image pixels that fit into one screen space unit equals <code>scale</code>, then image with size <code>scale</code> * 19 will be selected. Initially only scales 1 and 2 will be supported. At least one image must be specified. Note that 'details.path = foo' is equivalent to 'details.imageData = {'19': foo}'"
|
||||
},
|
||||
"tabId": {
|
||||
"type": "integer",
|
||||
"optional": true,
|
||||
"description": "Limits the change to when a particular tab is selected. Automatically resets when the tab is closed."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "callback",
|
||||
"optional": true,
|
||||
"parameters": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "setPopup",
|
||||
"type": "function",
|
||||
"description": "Sets the html document to be opened as a popup when the user clicks on the browser action's icon.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "details",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"tabId": {
|
||||
"type": "integer",
|
||||
"optional": true,
|
||||
"minimum": 0,
|
||||
"description": "Limits the change to when a particular tab is selected. Automatically resets when the tab is closed."
|
||||
},
|
||||
"popup": {
|
||||
"type": "string",
|
||||
"description": "The html file to show in a popup. If set to the empty string (''), no popup is shown."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getPopup",
|
||||
"type": "function",
|
||||
"description": "Gets the html document set as the popup for this browser action.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "details",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"tabId": {
|
||||
"type": "integer",
|
||||
"optional": true,
|
||||
"description": "Specify the tab to get the popup from. If no tab is specified, the non-tab-specific popup is returned."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "callback",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "result",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "setBadgeText",
|
||||
"type": "function",
|
||||
"description": "Sets the badge text for the browser action. The badge is displayed on top of the icon.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "details",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"text": {
|
||||
"type": "string",
|
||||
"description": "Any number of characters can be passed, but only about four can fit in the space."
|
||||
},
|
||||
"tabId": {
|
||||
"type": "integer",
|
||||
"optional": true,
|
||||
"description": "Limits the change to when a particular tab is selected. Automatically resets when the tab is closed."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getBadgeText",
|
||||
"type": "function",
|
||||
"description": "Gets the badge text of the browser action. If no tab is specified, the non-tab-specific badge text is returned.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "details",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"tabId": {
|
||||
"type": "integer",
|
||||
"optional": true,
|
||||
"description": "Specify the tab to get the badge text from. If no tab is specified, the non-tab-specific badge text is returned."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "callback",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "result",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "setBadgeBackgroundColor",
|
||||
"type": "function",
|
||||
"description": "Sets the background color for the badge.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "details",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"color": {
|
||||
"description": "An array of four integers in the range [0,255] that make up the RGBA color of the badge. For example, opaque red is <code>[255, 0, 0, 255]</code>. Can also be a string with a CSS value, with opaque red being <code>#FF0000</code> or <code>#F00</code>.",
|
||||
"choices": [
|
||||
{"type": "string"},
|
||||
{"$ref": "ColorArray"}
|
||||
]
|
||||
},
|
||||
"tabId": {
|
||||
"type": "integer",
|
||||
"optional": true,
|
||||
"description": "Limits the change to when a particular tab is selected. Automatically resets when the tab is closed."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "getBadgeBackgroundColor",
|
||||
"type": "function",
|
||||
"description": "Gets the background color of the browser action.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "details",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"tabId": {
|
||||
"type": "integer",
|
||||
"optional": true,
|
||||
"description": "Specify the tab to get the badge background color from. If no tab is specified, the non-tab-specific badge background color is returned."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "function",
|
||||
"name": "callback",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "result",
|
||||
"$ref": "ColorArray"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "enable",
|
||||
"type": "function",
|
||||
"description": "Enables the browser action for a tab. By default, browser actions are enabled.",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"optional": true,
|
||||
"name": "tabId",
|
||||
"minimum": 0,
|
||||
"description": "The id of the tab for which you want to modify the browser action."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "disable",
|
||||
"type": "function",
|
||||
"description": "Disables the browser action for a tab.",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"optional": true,
|
||||
"name": "tabId",
|
||||
"minimum": 0,
|
||||
"description": "The id of the tab for which you want to modify the browser action."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "openPopup",
|
||||
"type": "function",
|
||||
"description": "Opens the extension popup window in the active window but does not grant tab permissions.",
|
||||
"unsupported": true,
|
||||
"parameters": [
|
||||
{
|
||||
"type": "function",
|
||||
"name": "callback",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "popupView",
|
||||
"type": "object",
|
||||
"optional": true,
|
||||
"description": "JavaScript 'window' object for the popup window if it was succesfully opened.",
|
||||
"additionalProperties": { "type": "any" }
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"name": "onClicked",
|
||||
"type": "function",
|
||||
"description": "Fired when a browser action icon is clicked. This event will not fire if the browser action has a popup.",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "tab",
|
||||
"$ref": "tabs.Tab"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
|
@ -4,5 +4,6 @@
|
|||
|
||||
browser.jar:
|
||||
content/browser/schemas/bookmarks.json
|
||||
content/browser/schemas/browser_action.json
|
||||
content/browser/schemas/tabs.json
|
||||
content/browser/schemas/windows.json
|
||||
|
|
|
@ -29,25 +29,25 @@ add_task(function* testTabSwitchContext() {
|
|||
"popup": browser.runtime.getURL("2.html"),
|
||||
"title": "Title 2",
|
||||
"badge": "2",
|
||||
"badgeBackgroundColor": [0xff, 0, 0],
|
||||
"badgeBackgroundColor": [0xff, 0, 0, 0xff],
|
||||
"disabled": true },
|
||||
{ "icon": browser.runtime.getURL("1.png"),
|
||||
"popup": browser.runtime.getURL("default-2.html"),
|
||||
"title": "Default Title 2",
|
||||
"badge": "d2",
|
||||
"badgeBackgroundColor": [0, 0xff, 0],
|
||||
"badgeBackgroundColor": [0, 0xff, 0, 0xff],
|
||||
"disabled": true },
|
||||
{ "icon": browser.runtime.getURL("1.png"),
|
||||
"popup": browser.runtime.getURL("default-2.html"),
|
||||
"title": "Default Title 2",
|
||||
"badge": "d2",
|
||||
"badgeBackgroundColor": [0, 0xff, 0],
|
||||
"badgeBackgroundColor": [0, 0xff, 0, 0xff],
|
||||
"disabled": false },
|
||||
{ "icon": browser.runtime.getURL("default-2.png"),
|
||||
"popup": browser.runtime.getURL("default-2.html"),
|
||||
"title": "Default Title 2",
|
||||
"badge": "d2",
|
||||
"badgeBackgroundColor": [0, 0xff, 0] },
|
||||
"badgeBackgroundColor": [0, 0xff, 0, 0xff] },
|
||||
];
|
||||
|
||||
let tabs = [];
|
||||
|
@ -83,7 +83,7 @@ add_task(function* testTabSwitchContext() {
|
|||
browser.browserAction.setPopup({ tabId, popup: "2.html" });
|
||||
browser.browserAction.setTitle({ tabId, title: "Title 2" });
|
||||
browser.browserAction.setBadgeText({ tabId, text: "2" });
|
||||
browser.browserAction.setBadgeBackgroundColor({ tabId, color: [0xff, 0, 0] });
|
||||
browser.browserAction.setBadgeBackgroundColor({ tabId, color: [0xff, 0, 0, 0xff] });
|
||||
browser.browserAction.disable(tabId);
|
||||
|
||||
expectDefaults(details[0]).then(() => {
|
||||
|
@ -116,7 +116,7 @@ add_task(function* testTabSwitchContext() {
|
|||
browser.browserAction.setPopup({ popup: "default-2.html" });
|
||||
browser.browserAction.setTitle({ title: "Default Title 2" });
|
||||
browser.browserAction.setBadgeText({ text: "d2" });
|
||||
browser.browserAction.setBadgeBackgroundColor({ color: [0, 0xff, 0] });
|
||||
browser.browserAction.setBadgeBackgroundColor({ color: [0, 0xff, 0, 0xff] });
|
||||
browser.browserAction.disable();
|
||||
expectDefaults(details[3]).then(() => {
|
||||
expect(details[3]);
|
||||
|
|
|
@ -614,6 +614,7 @@ BrowserGlue.prototype = {
|
|||
ExtensionManagement.registerScript("chrome://browser/content/ext-bookmarks.js");
|
||||
|
||||
ExtensionManagement.registerSchema("chrome://browser/content/schemas/bookmarks.json");
|
||||
ExtensionManagement.registerSchema("chrome://browser/content/schemas/browser_action.json");
|
||||
ExtensionManagement.registerSchema("chrome://browser/content/schemas/tabs.json");
|
||||
ExtensionManagement.registerSchema("chrome://browser/content/schemas/windows.json");
|
||||
|
||||
|
|
|
@ -9,6 +9,11 @@ const Cc = Components.classes;
|
|||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
|
||||
var {
|
||||
instanceOf,
|
||||
} = ExtensionUtils;
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["Schemas"];
|
||||
|
||||
/* globals Schemas */
|
||||
|
@ -127,6 +132,8 @@ class ChoiceType extends Type {
|
|||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return {error: "No valid choice"};
|
||||
}
|
||||
|
||||
checkBaseType(baseType) {
|
||||
|
@ -209,21 +216,12 @@ class StringType extends Type {
|
|||
}
|
||||
}
|
||||
|
||||
class UnrestrictedObjectType extends Type {
|
||||
normalize(value) {
|
||||
return this.normalizeBase("object", value);
|
||||
}
|
||||
|
||||
checkBaseType(baseType) {
|
||||
return baseType == "object";
|
||||
}
|
||||
}
|
||||
|
||||
class ObjectType extends Type {
|
||||
constructor(properties, additionalProperties) {
|
||||
constructor(properties, additionalProperties, isInstanceOf) {
|
||||
super();
|
||||
this.properties = properties;
|
||||
this.additionalProperties = additionalProperties;
|
||||
this.isInstanceOf = isInstanceOf;
|
||||
}
|
||||
|
||||
checkBaseType(baseType) {
|
||||
|
@ -236,6 +234,21 @@ class ObjectType extends Type {
|
|||
return v;
|
||||
}
|
||||
|
||||
if (this.isInstanceOf) {
|
||||
if (Object.keys(this.properties).length ||
|
||||
!(this.additionalProperties instanceof AnyType)) {
|
||||
throw new Error("InternalError: isInstanceOf can only be used with objects that are otherwise unrestricted");
|
||||
}
|
||||
|
||||
if (!instanceOf(value, this.isInstanceOf)) {
|
||||
return {error: `Object must be an instance of ${this.isInstanceOf}`};
|
||||
}
|
||||
|
||||
// This is kind of a hack, but we can't normalize things that
|
||||
// aren't JSON, so we just return them.
|
||||
return {value};
|
||||
}
|
||||
|
||||
let result = {};
|
||||
for (let prop of Object.keys(this.properties)) {
|
||||
let {type, optional, unsupported} = this.properties[prop];
|
||||
|
@ -341,10 +354,11 @@ class BooleanType extends Type {
|
|||
}
|
||||
|
||||
class ArrayType extends Type {
|
||||
constructor(itemType, minItems) {
|
||||
constructor(itemType, minItems, maxItems) {
|
||||
super();
|
||||
this.itemType = itemType;
|
||||
this.minItems = minItems;
|
||||
this.maxItems = maxItems;
|
||||
}
|
||||
|
||||
normalize(value) {
|
||||
|
@ -366,6 +380,10 @@ class ArrayType extends Type {
|
|||
return {error: `Array requires at least ${this.minItems} items; you have ${result.length}`};
|
||||
}
|
||||
|
||||
if (result.length > this.maxItems) {
|
||||
return {error: `Array requires at most ${this.maxItems} items; you have ${result.length}`};
|
||||
}
|
||||
|
||||
return {value: result};
|
||||
}
|
||||
|
||||
|
@ -626,12 +644,8 @@ this.Schemas = {
|
|||
type.minLength || 0,
|
||||
type.maxLength || Infinity);
|
||||
} else if (type.type == "object") {
|
||||
if (!type.properties) {
|
||||
checkTypeProperties();
|
||||
return new UnrestrictedObjectType();
|
||||
}
|
||||
let properties = {};
|
||||
for (let propName of Object.keys(type.properties)) {
|
||||
for (let propName of Object.keys(type.properties || {})) {
|
||||
let propType = this.parseType(namespaceName, type.properties[propName],
|
||||
["optional", "unsupported", "deprecated"]);
|
||||
properties[propName] = {
|
||||
|
@ -646,11 +660,12 @@ this.Schemas = {
|
|||
additionalProperties = this.parseType(namespaceName, type.additionalProperties);
|
||||
}
|
||||
|
||||
return new ObjectType(properties, additionalProperties);
|
||||
checkTypeProperties("properties", "additionalProperties", "isInstanceOf");
|
||||
return new ObjectType(properties, additionalProperties, type.isInstanceOf);
|
||||
} else if (type.type == "array") {
|
||||
checkTypeProperties("items", "minItems");
|
||||
checkTypeProperties("items", "minItems", "maxItems");
|
||||
return new ArrayType(this.parseType(namespaceName, type.items),
|
||||
type.minItems || 0);
|
||||
type.minItems || 0, type.maxItems || Infinity);
|
||||
} else if (type.type == "number") {
|
||||
checkTypeProperties();
|
||||
return new NumberType();
|
||||
|
|
|
@ -123,7 +123,7 @@ let json = [
|
|||
name: "quosimodo",
|
||||
type: "function",
|
||||
parameters: [
|
||||
{name: "xyz", type: "object"},
|
||||
{name: "xyz", type: "object", additionalProperties: {type: "any"}},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
Загрузка…
Ссылка в новой задаче