Add collapsible blocks describing parameters of actions/conditions in the documentation

This commit is contained in:
Florian Rival
2025-10-11 17:49:19 +02:00
parent 6d67965c63
commit f05fa88eec
3 changed files with 182 additions and 11 deletions

View File

@@ -518,11 +518,16 @@ initializeGDevelopJs().then(async gd => {
try {
console.info(` Loading all community extensions...`);
let indexPageContent = `# Extensions
let indexPageContent = `---
icon: material/puzzle
---
# Extensions
GDevelop is built in a flexible way. In addition to [core features](/gdevelop5/all-features), new capabilities are provided by extensions. Extensions can contain objects, behaviors, actions, conditions, expressions or events.
In addition to [core features](/gdevelop5/all-features), new capabilities are provided by extensions. Extensions can contain objects, behaviors, actions, conditions, expressions, effects or events.
Official as well as experimental extensions are accessible [directly from GDevelop](/gdevelop5/extensions/search).
A list of [community-made extensions is available on GitHub](https://github.com/GDevelopApp/GDevelop-community-list).
Community created extensions are accessible [directly from GDevelop](/gdevelop5/extensions/search).
New extensions can also be [created](/gdevelop5/extensions/create) from scratch using events or JavaScript.
Read more about this:

View File

@@ -93,7 +93,10 @@ const generateAllExtensionReferences = gd => {
*/
const generateAllFeaturesStartPageRawTexts = extensionReferences => {
const headerText = {
text: `# All features
text: `---
icon: material/star-circle
---
# All features
This page lists **all the features** that are provided in GDevelop. These can be objects, behaviors but also features that can be used directly using actions, conditions or expressions (without requiring an object to be existing on the scene).

View File

@@ -170,6 +170,7 @@ const translateTypeToHumanReadableDescription = type => {
if (type === 'expression') return '🔢 Number';
if (type === 'camera') return '🔢 Camera index (Number)';
if (type === 'object') return '👾 Object';
if (type === 'objectList') return '👾 Object';
if (type === 'objectPtr') return '👾 Object';
if (type === 'objectListOrEmptyIfJustDeclared') return '👾 Object';
@@ -200,6 +201,12 @@ const translateTypeToHumanReadableDescription = type => {
if (type === 'externalLayoutName') return '🔤 External Layout Name (String)';
if (type === 'leaderboardId') return '🔤 Leaderboard Identifier (String)';
if (type === 'operator') return '🟰 Operator';
if (type === 'relationalOperator') return '🟰 Relational operator';
if (type === 'yesorno') return '❓ Yes or No';
if (type === 'trueorfalse') return '❓ True or False';
return type;
};
@@ -235,9 +242,101 @@ const translateTypeToHumanReadableType = type => {
if (type === 'externalLayoutName') return 'external layout name';
if (type === 'leaderboardId') return 'leaderboard identifier';
if (type === 'yesorno') return 'yes or no';
if (type === 'trueorfalse') return 'true or false';
return type;
};
/**
* @param {string} type
* @param {string} sanitizedDescription
*/
const isDescriptionObvious = (type, sanitizedDescription) => {
const isDescriptionSameAsType =
sanitizedDescription.toLowerCase().replace(/\s+/g, '') ===
type.toLowerCase();
if (isDescriptionSameAsType) return true;
if (
type === 'number' &&
(sanitizedDescription === 'Expression' ||
sanitizedDescription === 'Expression (number)' ||
sanitizedDescription === 'Expression.')
)
return true;
if (type === 'operator' || type === 'relationalOperator') {
return true;
}
if (
type === 'layerEffectName' ||
type === 'layerEffectParameterName' ||
type === 'objectEffectName' ||
type === 'objectEffectParameterName' ||
type === 'objectPointName' ||
type === 'objectAnimationName' ||
type === 'externalLayoutName'
) {
return true;
}
return false;
};
const normalizeType = (/** @type {string} */ parameterType) => {
if (parameterType === 'expression') return 'number';
if (
parameterType === 'object' ||
parameterType === 'objectPtr' ||
parameterType === 'objectList' ||
parameterType === 'objectListOrEmptyIfJustDeclared' ||
parameterType === 'objectListOrEmptyWithoutPicking'
) {
return 'object';
}
return parameterType;
};
/**
* @param {string} type
* @param {string} sanitizedDescription
*/
const getSimplifiedParameterDescription = (type, sanitizedDescription) => {
if (
type === 'number' &&
sanitizedDescription.toLowerCase().includes('camera number')
) {
return 'Camera number';
}
return null;
};
/**
* @param {ParameterMetadata} parameterMetadata
* @returns {string}
*/
const getParameterExtraInfoDescription = parameterMetadata => {
if (parameterMetadata.getType() === 'stringWithSelector') {
const rawExtraInfo = parameterMetadata.getExtraInfo();
try {
const parsedExtraInfo = JSON.parse(rawExtraInfo);
if (Array.isArray(parsedExtraInfo)) {
return `(one of: ${parsedExtraInfo
.map(value => `"${value}"`)
.join(', ')})`;
}
} catch (err) {
return `(value must be: ${rawExtraInfo})`;
}
}
return '';
};
/** @returns {ReferenceText} */
const generateInstructionReferenceRowsText = ({
instructionType,
@@ -246,15 +345,79 @@ const generateInstructionReferenceRowsText = ({
objectMetadata,
behaviorMetadata,
}) => {
const paramPadding = ' ';
const codeOnlyParametersIndexes = [];
let parametersList = mapFor(
0,
instructionMetadata.getParameters().getParametersCount(),
index => {
const parameterMetadata = instructionMetadata
.getParameters()
.getParameterAt(index);
const longDescription = parameterMetadata.getLongDescription();
const sanitizedDescription = [
parameterMetadata.getDescription(),
longDescription,
]
.filter(Boolean)
.join('\n')
.replace(/\n/g, `\n${paramPadding} `);
const type = normalizeType(parameterMetadata.getType());
const humanReadableTypeDesc = translateTypeToHumanReadableDescription(
type
);
if (parameterMetadata.isCodeOnly()) {
codeOnlyParametersIndexes.push(index);
return null;
}
const simplifiedParameterDescription = getSimplifiedParameterDescription(
type,
sanitizedDescription
);
const extraInfoDescription = getParameterExtraInfoDescription(
parameterMetadata
);
return [
simplifiedParameterDescription
? `${paramPadding}- Parameter ${index} (${humanReadableTypeDesc}): ${simplifiedParameterDescription}`
: isDescriptionObvious(type, sanitizedDescription)
? `${paramPadding}- Parameter ${index}: ${humanReadableTypeDesc}`
: `${paramPadding}- Parameter ${index} (${humanReadableTypeDesc}): ${sanitizedDescription}`,
extraInfoDescription,
]
.filter(Boolean)
.join(' ');
}
)
.filter(Boolean)
.join('\n');
if (codeOnlyParametersIndexes.length) {
parametersList +=
'\n\n' +
`${paramPadding}> Technical note: ${
codeOnlyParametersIndexes.length === 1 ? 'parameter' : 'parameters'
} ${codeOnlyParametersIndexes.join(
', '
)} are internal parameters handled by GDevelop.`;
}
return {
orderKey: instructionType,
text:
'**' +
instructionMetadata.getFullName() +
'** ' +
'\n' +
instructionMetadata.getDescription().replace(/\n/, ' \n') +
'\n',
text: [
'**' + instructionMetadata.getFullName() + '**',
instructionMetadata.getDescription().replace(/\n/, ` \n`),
'',
...(parametersList
? ['??? quote "See parameters"', '', parametersList, '']
: []),
].join('\n'),
};
};