Skip to content

Commit

Permalink
Better handling of specific types
Browse files Browse the repository at this point in the history
  • Loading branch information
markwpearce committed Sep 1, 2022
1 parent 0b18845 commit b8eb9b3
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 13 deletions.
63 changes: 59 additions & 4 deletions scripts/scrape-roku-docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,17 @@ import { gfm } from '@guyplusplus/turndown-plugin-gfm';
import { marked } from 'marked';
import * as he from 'he';
import * as deepmerge from 'deepmerge';
import { StringType } from '../src/types/StringType';

type Token = marked.Token;

const potentialTypes = ['object', 'integer', 'float', 'boolean', 'string', 'dynamic', 'function', 'longinteger', 'double', 'roassociativearray', 'object (string array)'];

const foundTypesTranslation = {
'object (string array)': 'object'
'object (string array)': 'object',
'robytearray object': 'roByteArray',
'rolist of roassociativearray items': 'roList',
'roassociative array': 'roAssociativeArray'
};

const turndownService = new TurndownService({
Expand Down Expand Up @@ -367,7 +371,7 @@ class Runner {
name: this.sanitizeMarkdownSymbol(paramName),
default: null,
isRequired: !isOptional,
type: paramType ?? 'dynamic',
type: chooseMoreSpecificType(paramType ?? 'dynamic'),
description: undefined
} as Param;
}
Expand Down Expand Up @@ -669,7 +673,7 @@ class Runner {

const methodParam = method.params.find(p => p?.name && p.name?.toLowerCase() === rowNameSanitized);
if (methodParam) {
methodParam.type = methodParam.type ?? row.type;
methodParam.type = chooseMoreSpecificType(methodParam.type, row.type);
methodParam.description = row.description ?? methodParam.description;
}
}
Expand Down Expand Up @@ -819,6 +823,57 @@ function objectKeySorter(key, value) {
: value;
}

/**
* For two types (or arrays of types), chooses the group that's "more specific"
*
* @param typeOne the first type group or string
* @param typeTwo the first type group or string
* @returns a type (or group of types) that is more specific
*/
function chooseMoreSpecificType(typeOne: string | string[] = 'dynamic', typeTwo: string | string[] = 'dynamic'): string | string[] {

// deals with issue where it says "roScreen or roBitmap", etc
// also when there is a problematic space, eg "roAssoc Array"
const splitRegex = /,|\sor\s/;
if (typeof typeOne === 'string') {
typeOne = typeOne.split(splitRegex);
}
if (typeof typeTwo === 'string') {
typeTwo = typeTwo.split(splitRegex);
}
const typeOneArray = typeOne.map(paramType => foundTypesTranslation[paramType.toLowerCase()] || paramType);
const typeTwoArray = typeTwo.map(paramType => foundTypesTranslation[paramType.toLowerCase()] || paramType);

function getSingle(strArray: string[]): string | string[] {
return strArray.length === 1 ? strArray[0] : strArray;
}

if (typeTwo.map(a => a.toLowerCase()).includes('dynamic')) {
// the second group has "dynamic" in it, so prefer the first group
return getSingle(typeOneArray);
} else if (typeOne.map(a => a.toLowerCase()).includes('dynamic')) {
// second group does not have dynamic, but first does, so 2nd group is more specific
return getSingle(typeTwoArray);
} else if (typeOneArray.length > typeTwoArray.length) {
// first group has more types
return getSingle(typeOneArray);
} else if (typeTwoArray.length > typeOneArray.length) {
// 2nd group has more types
return getSingle(typeTwoArray);
} else if (typeOneArray.length === 1 && typeTwoArray.length === 1) {
// both have one type
if (typeOneArray[0].toLowerCase() === 'object' && typeTwoArray[0].toLowerCase().startsWith('ro')) {
// the first type is "Object", but is more specific in second type
return getSingle(typeTwoArray);
}
if (typeTwoArray[0].toLowerCase() === 'object') {
// Second type is Object ... so prefer the 1st, which usually comes from a code line
return getSingle(typeOneArray);
}
}
return getSingle(typeOneArray);
}

/**
* A class to help manage the parsed markdown tokens
*/
Expand Down Expand Up @@ -1130,7 +1185,7 @@ interface Param {
isRequired: boolean;
description: string;
default: string;
type: string;
type: string | string[];
}
interface Prop {
name: string;
Expand Down
21 changes: 12 additions & 9 deletions src/roku-types/data.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"generatedDate": "2022-05-12T16:31:04.770Z",
"generatedDate": "2022-09-01T18:08:56.091Z",
"nodes": {
"animation": {
"description": "Extends [**AnimationBase**](https://developer.roku.com/docs/references/scenegraph/abstract-nodes/animationbase.md\n\nThe Animation node class provides animations of renderable nodes, by applying interpolator functions to the values in specified renderable node fields. For an animation to take effect, an Animation node definition must include a child field interpolator node ([FloatFieldInterpolator](https://developer.roku.com/docs/references/scenegraph/animation-nodes/floatfieldinterpolator.md\"FloatFieldInterpolator\"), [Vector2DFieldInterpolator](https://developer.roku.com/docs/references/scenegraph/animation-nodes/vector2dfieldinterpolator.md\"Vector2DFieldInterpolator\"), [ColorFieldInterpolator](https://developer.roku.com/docs/references/scenegraph/animation-nodes/colorfieldinterpolator.md\"ColorFieldInterpolator\")) definition for each renderable node field that is animated.\n\nThe Animation node class provides a simple linear interpolator function, where the animation takes place smoothly and simply from beginning to end. The Animation node class also provides several more complex interpolator functions to allow custom animation effects. For example, you can move a graphic image around the screen at differing speeds and curved trajectories at different times in the animation by specifying the appropriate function in the easeFunction field (quadratic and exponential are two examples of functions that can be specified). The interpolator functions are divided into two parts: the beginning of the animation (ease-in), and the end of the animation (ease-out). You can apply a specified interpolator function to either or both ease-in and ease-out, or specify no function for either or both (which is the linear function). You can also change the portion of the animation that is ease-in and ease-out to arbitrary fractional values for a quadratic interpolator function applied to both ease-in and ease-out.",
Expand Down Expand Up @@ -8387,7 +8387,7 @@
"description": "Key-value pairs specifying the playback experience upon launching the channel. For example, if deep linking parameters are passed into the method, the content ID specifies the content to be played upon launching the channel, and the mediaType determines whether the content is launched directly into playback, launched into playback using bookmarks, or an episode selection screen for the content is displayed). To launch the channel store springboard of a channel, use the **ShowChannelStoreSpringboard()** method. You can also do this by passing a channelID of \"11\" is passed into this method (`LaunchApp(\"11\", \"\", params)`). In this case, the params field would include a content ID (`params = {contentID: \"myAwesomeMovie_123\"}`).",
"isRequired": true,
"name": "params",
"type": "Object"
"type": "roAssociativeArray"
}
],
"returnType": "Void"
Expand Down Expand Up @@ -8415,7 +8415,7 @@
"description": "The video or audio [content metadata](/docs/developer-program/getting-started/architecture/content-metadata.md) parameters to be updated (for example, the title and contentType)",
"isRequired": true,
"name": "contentMetaData",
"type": "Object"
"type": "roAssociativeArray"
}
],
"returnType": "Void"
Expand Down Expand Up @@ -9654,7 +9654,10 @@
"description": "The [roScreen](https://developer.roku.com/docs/references/brightscript/components/roscreen.md or [roImageCanvas](https://developer.roku.com/docs/references/brightscript/components/roimagecanvas.md instance to be associated with this caption renderer.",
"isRequired": true,
"name": "screen",
"type": "Object"
"type": [
"roScreen",
"roImageCanvas"
]
}
],
"returnType": "Void"
Expand Down Expand Up @@ -9823,14 +9826,14 @@
"description": "Each roAssociativeArray in the roList contains the following fields: <table><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>code</td><td>String</td><td>The product identifier</td></tr><tr><td>qty</td><td>Integer</td><td>The quantity purchased</td></tr></tbody></table>",
"isRequired": true,
"name": "order",
"type": "Object"
"type": "roList"
},
{
"default": null,
"description": "_Available since Roku OS 9.3_ This parameter is used for subscription upgrades and downgrades. If it is not specified, the action is a product purchase. It contains the following fields: <table><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>action</td><td>String</td><td>The action to be performed, which may be one of the following:<ul><li>\"Upgrade\": The order is an upgrade from one subscription product to another.</li><li>\"Downgrade\": The order is a subscription downgrade.</li></ul></td></tr></tbody></table> **Example** ``` m.store = CreateObject(\"roChannelStore\")​ ' Populate myOrderItems myOrderInfo.action = \"Upgrade\" m.store.setOrder(myOrderItems, myOrderInfo) ``` See [On-device upgrade and downgrade](/docs/developer-program/roku-pay/implementation/on-device-upgrade-downgrade.md#calling-the-roku-web-service-validate-transaction-api) for how to implement Roku Pay web services for upgrades/downgrades.",
"isRequired": true,
"name": "orderInfo",
"type": "Object"
"type": "roAssociativeArray"
}
],
"returnType": "Void"
Expand Down Expand Up @@ -15520,7 +15523,7 @@
"description": "The roByteArray to be signed. Errors will be printed in the BrightScript console. If the digest algorithm is not set (using SetDigestAlgorithm) before calling Sign(), the digest is not encapsulated. This would be equivalent to simply calling the openssl function RSA\\_private\\_encrypt()",
"isRequired": true,
"name": "digest",
"type": "Object"
"type": "roByteArray"
}
],
"returnDescription": "An roByteArray containing the signature, or invalid if an error occurred. Typical values include the following:",
Expand All @@ -15535,14 +15538,14 @@
"description": "The digest to be verified.",
"isRequired": true,
"name": "digest",
"type": "Object"
"type": "roByteArray"
},
{
"default": null,
"description": "The signature to be verified.",
"isRequired": true,
"name": "signature",
"type": "Object"
"type": "roByteArray"
}
],
"returnDescription": "Indicates the result of the validation. This may be one of the following values:",
Expand Down

0 comments on commit b8eb9b3

Please sign in to comment.