docsforadobe.dev
byhttps://docsforadobe.dev
Hosted at | https://.docsforadobe.dev/ |
Repository | https://github.com/docsforadobe/docsforadobe.dev |
Copyright | All content is copyright Adobe Systems Incorporated. |
Table of Contents
Contributing ↵
Contribution Guide¶
This endeavour is primarily community-supported & run; contributors are welcome and encouraged to suggest fixes, adjustments, notes/warnings, and anything else that may help the project.
This project is written in Markdown, served using MkDocs, themed with Material for MkDocs.
Note
Broad info on Markdown syntax is outside the scope of this guide. Please familiarise yourself with it before contributing.
Contributing¶
This contribution guide is split into a few chapters.
Tip
This repo itself may not adhere to the standards above, as we're using a number of custom features to help demonstrate best practices.
If in doubt, follow the above guides and templates, not the source code of this contribution guide.
Licensing & Ownership¶
This project exists for educational purposes only.
All content is copyright Adobe Systems Incorporated.
Getting Set Up¶
While it's technically possible to start contributing just through editing the markdown, we ask that you build the project locally to test your changes & ensure the result is what you'd expect.
To start working locally, you'll need to:
Quickstart guide
Assuming you're familiar with some of the below, here's a quick example way to get set up:
# Clone target repo
git clone https://github.com/docsforadobe/after-effects-scripting-guide.git
# Navigate to that directory
cd after-effects-scripting-guide
# Install dependencies
pip install -r requirements.txt
# Serve the docs
mkdocs serve
Install Python¶
This project runs on Python & dependent packages.
You'll need to install Python 3 & pip (a Python package manager; typically comes with Python installs)
Note
Specific Python installation instructions will depend on your OS; see above links for more info.
Download the repo locally¶
From a terminal, enter the command:
git clone path/to/repo.git
For example, to download the After Effects Scripting Guide:
git clone https://github.com/docsforadobe/after-effects-scripting-guide.git
Install dependencies¶
Once Python is installed, you'll need to install the required dependencies for the specific documentation guide you're working in.
The dependencies for each repo is held in a text file in the root of the repo, requirements.txt
.
These are things like the actual system used to build the project ("MkDocs"), as well as any plugins or extensions required for the specific guide you're working in.
First, open a terminal to the repo's directory.
Then, you can tell Python to install these dependencies globally onto your device with the following command:
pip install -r requirements.txt
If you're wanting to install these locally (for just the local user), you can append the --user
flag:
pip install -r requirements.txt --user
MacOS & Virtual Environments¶
On MacOS, you may need to set up a virtual environment in order for Python to allow you to install these dependencies.
This author isn't familiar enough to explain why this is required, though these commands seem to do the trick before running the pip
command above.
python3 -m venv venv/
source venv/bin/activate
This will create a subfolder in the directory, /venv/
, that will hold these dependencies. These files should not be committed to the repo, with /venv/
being present in each repo's .gitignore
file.
Build the project¶
Once the dependencies are installed, you can run the following command to build a local copy of the docs:
mkdocs serve
This will set up a virtual server, render the docs to html, and offer up a local url to view these local docs at.
By default, this local url is http://127.0.0.1:8000
.
Tip
Any update to the MkDocs config file (./mkdocs.yml
) or any of the .md docs files will automagically reload the above pages, showing the updates!
Be sure to keep an eye on the terminal for any potential errors or warnings that may come up while working.
Style Guide¶
These guides are primarily written in plain, vanilla markdown. With that said, in order to maintain a consistent experience across docs, we require contributors to adhere to some opinionated decisions.
In addition, we are making use of some specific features & syntax decisions introduced by the current rendering framework being used (MkDocs for the engine, Material for MkDocs for the theme base).
This page serves to clarify some of these decisions, as well as specific tips and workflows for ensuring consistency.
Note
If anything is unclear or should be re-evaluated, please open a ticket or discussion post in the Github org.
Writing Tips¶
- Do not manually insert linebreaks! Let the text be long; it will wrap as necessary upon render.
- Any indented blocks require four spaces in order to properly nest. This applies to lists, admonitions, nested content blocks, and more. Four spaces!
- As frequently as possible, add crosslinks in the guides!
- If an attribute returns an object that's also documented, adding in a crosslink from the attribute's "type" to the other object's page greatly improves the user experience in these guides.
Title Hierarchy¶
The below is the most common general structure, though of course will depend on any specific guide or page's needs.
# Page
## Category ("Attributes", "Methods")
### Attribute/Method Name ("CharacterRange.characterEnd")
#### Info Header ("Description", "Type", "Parameters", "Returns")
Element Templating¶
Typically, we try to ensure consistency between all Class pages across the docs, and between all Attributes and Methods.
Class Pages¶
These should broadly be structured following the below template. Note that not all page elements may apply, or some other page elements may be added as needed.
Note that depending on the specific page format, the 'depth' of each title (as far as number of #
) may change.
# Page Title
`sample.call`
#### Description
Description of this class
#### Example
Class-wide example(s), if applicable
---
## Attributes
{ list of attributes }
---
## Methods
{ list of attributes }
# Layer object
`app.project.item(index).layer(index)`
#### Description
The Layer object provides access to layers within compositions. It can be accessed from an item's layer collection either by index number or by a name string.
#### Example
If the first item in the project is a [CompItem](../item/compitem.md), this example disables the first layer in that composition and renames it. This might, for example, turn an icon off in the composition.
`var layer = app.project.item(1).layer(1);`
---
## Attributes
---
## Methods
Attributes¶
In this context, attributes are synonymous with object properties. (ie class.attribute
, e.g. layer.name
).
The base attribute template should look similar to:
### Class.attributeName
`sample.attribute.call`
#### Description
Attribute description
#### Type
Property Type. { Read-only, if applicable. }
{ If enum, list possible options. }
{ If an object, create a table of object properties. }
### Layer.autoOrient
`app.project.item(index).layer(index).autoOrient`
#### Description
The type of automatic orientation to perform for the layer.
#### Type
An `AutoOrientType` enumerated value; read/write. One of:
- `AutoOrientType.ALONG_PATH` Layer faces in the direction of the motion path.
- `AutoOrientType.CAMERA_OR_POINT_OF_INTEREST` Layer always faces the active camera or points at its point of interest.
- `AutoOrientType.CHARACTERS_TOWARD_CAMERA` Each character in a per-character 3D text layer automatically faces the active camera.
- `AutoOrientType.NO_AUTO_ORIENT` Layer rotates freely, independent of any motion path, point of interest, or other layers.
Methods¶
Methods are formatted similarly to attributes, with two primary differences:
- The addition of the
Parameters
section, including a table of parameters - The use of
Returns
in lieu ofType
for the method's returned type.
For all parameters & property tables, please include the type of each parameter / property!
### Class.methodName()
`sample.method.call()`
#### Description
Method description
#### Parameters { If applicable }
| Parameter | Type | Description |
| --------------- | --------- | ----------- |
| `parameterName` | Item type | Description |
#### Returns
Property Type.
{ If enum, list possible options. }
{ If an object, create a table of object properties. }
### Layer.activeAtTime()
`app.project.item(index).layer(index).activeAtTime(time)`
#### Description
Returns `true` if this layer will be active at the specified time.
To return `true`, the layer must be enabled, no other layer may be soloing unless this layer is soloed too, and the time must be between the `inPoint` and `outPoint` values of this layer.
#### Parameters
| Parameter | Type | Description |
| --------- | -------------------- | -------------------- |
| `time` | Floating-point value | The time in seconds. |
#### Returns
Boolean.
Tables¶
A large part of all of these guides are tables. Due to the various complexities within these guides, we'll be using two different styles of tables– what we're calling "simple" (standard markdown tables) and "complex" (markdown grid tables).
Simple Tables¶
These are to be used in cases where we don't require any complicated, nested content – when there's simple text formatting, one line of text, and when we don't need linebreaks, lists, admonitions, etc.
Those tables look generally like this (though any vanilla table syntax is acceptable to use, such as alignment options):
Header 1 | Header 2 | Header 3 |
---|---|---|
foo |
bar | 0.00 |
bar |
foo | 100.00 |
| Header 1 | Header 2 | Header 3 |
| -------- | -------- | -------: |
| `foo` | bar | 0.00 |
| `bar` | foo | 100.00 |
Complex Tables¶
When we want to include more info within a given row or column– think nested lists, line breaks, admonitions, etc– we'll be using these "grid tables".
Info
See this repo issue for more info and examples.
They differ in both syntax (as you'll see below), but also in that they require a divider between every row. You'll also need to ensure they're properly formatted (pipes aligned, etc) in order to render properly.
Title A |
Title B |
---|---|
Item 1.A |
Item 1.B Item 1.B Line 2 |
Item 2.A |
|
Item 3.A |
Item 3.B Warning Deprecated |
+----------+-----------------+
| Title A | Title B |
+==========+=================+
| Item 1.A | Item 1.B |
| | |
| | Item 1.B Line 2 |
+----------+-----------------+
| Item 2.A | - Item 2.B |
| | - Item 2.B |
+----------+-----------------+
| Item 3.A | Item 3.B |
| | |
| | !!! warning |
| | Deprecated |
+----------+-----------------+
Code Samples¶
There are three different contexts under which we'll be displaying code (or: wanting text to render as monospaced code).
Inline code¶
Typically, this is only used for quick, throwaway samples (or to identify something as code, or a variable name).
An example would be when discussing a boolean returning true
in one case, false
in another.
Or, in the description of an attribute, that you can access something by using Comp.layer(1)
– very simple samples.
An example would be when discussing a boolean returning `true` in one case, `false` in another.
Or, in the description of an attribute, that you can access something by using `Comp.layer(1)` – very simple samples.
Code fences¶
These are most often used for longer, more fleshed-out code samples.
Always include a language in the code fence description (so that the renderer can properly syntax highlight the code).
function err(errString) {
alert(errString) ;
}
app.onError = err;
extern "C" DllExport
PF_Err PluginDataEntryFunction(
PF_PluginDataPtr inPtr,
PF_PluginDataCB inPluginDataCallBackPtr,
SPBasicSuite* inSPBasicSuitePtr,
const char* inHostName,
const char* inHostVersion)
{
PF_Err result = PF_Err_INVALID_CALLBACK;
result = PF_REGISTER_EFFECT(
inPtr,
inPluginDataCallBackPtr,
"ColorGrid", // Name
"ADBE ColorGrid", // Match Name
"Sample Plug-ins", // Category
AE_RESERVED_INFO); // Reserved Info
return result;
}
set theFile to choose file
tell application "Adobe After Effects CS6"
DoScriptFile theFile
end tell
```javascript
function err(errString) {
alert(errString) ;
}
app.onError = err;
```
```cpp
extern "C" DllExport
PF_Err PluginDataEntryFunction(
PF_PluginDataPtr inPtr,
PF_PluginDataCB inPluginDataCallBackPtr,
SPBasicSuite* inSPBasicSuitePtr,
const char* inHostName,
const char* inHostVersion)
{
PF_Err result = PF_Err_INVALID_CALLBACK;
result = PF_REGISTER_EFFECT(
inPtr,
inPluginDataCallBackPtr,
"ColorGrid", // Name
"ADBE ColorGrid", // Match Name
"Sample Plug-ins", // Category
AE_RESERVED_INFO); // Reserved Info
return result;
}
```
```applescript
set theFile to choose file
tell application "Adobe After Effects CS6"
DoScriptFile theFile
end tell
```
Code fences within tables¶
This is the trickiest, and most annoying to work with.
As both code fences and markdown tables pay attention to line breaks, these features necessarily fight one another in order to break rendering.
To solve this, the only (currently-known) workaround is to wrap the code in html, so that it can be properly rendered as code. We need to replace line breaks with <br/>
, and wrap the whole block in <pre lang="lang"></pre>
(identifying the language)
Note
Be sure to identify the language here, for syntax highlighting purposes!
Here's a before/after of one a simple code sample:
```javascript
function err(errString) {
alert(errString) ;
}
app.onError = err;
```
<pre lang="javascript">function err(errString) {<br/> alert(errString) ;<br/>}<br/>app.onError = err;</pre>
And when placed within a table:
Tip
You'll likely want to be using complex tables, in order to add additional info about the example within the table itself.
Title |
Sample |
---|---|
Alert error |
This sample shows how to specify a callback function when an error occurs. function err(errString) {
|
+-------------+----------------------------------------------------------------------------------------------------------------+
| Title | Sample |
+=============+================================================================================================================+
| Alert error | This sample shows how to specify a callback function when an error occurs. |
| | |
| | <pre lang="javascript">function err(errString) {<br/> alert(errString) ;<br/>}<br/>app.onError = err;</pre> |
+-------------+----------------------------------------------------------------------------------------------------------------+
Admonitions¶
Often, we'll want to call out specific pieces of info to the end reader. Typically, these are in the form of notes, tips, and warnings though more admonitions can be used as appropriate.
To author these, use the following sytax. Note that the content must be indented with 4 spaces in the line following the header!
Adding in linebreaks, lists, code, etc. are all supported within admonitions.
Note¶
Notes detail version added, and/or relevant pieces of information.
Note
Notes detail version added, and/or relevant pieces of information.
!!! note
Notes detail version added, and/or relevant pieces of information.
Tip¶
Tips detail version added, and/or relevant pieces of information.
Tip
Tips detail version added, and/or relevant pieces of information.
!!! tip
Tips detail version added, and/or relevant pieces of information.
Warning¶
Warnings convey negative behaviours, or when something won't work the way you'd expect.
Warning
Warnings convey negative behaviours, or when something won't work the way you'd expect.
They're also used to indicate undocumented elements.
!!! warning
Warnings convey negative behaviours, or when something won't work the way you'd expect.
They're also used to indicate undocumented elements.
Other Tips¶
Various other tips, suggestions, solutions that we've found to be helpful when working on these guides.
Use code editor extensions!¶
As markdown is such a common language, there are a ton of code editor extensions to help writing it. Take advantage of them!
One specific place this can help is when working with tables. As these can get fairly long and unwieldy, being able to quickly format the table to align columns & fix formatting is way better than doing this by hand.
Adding undocumented attributes or methods¶
If you find attributes or methods that are not mentioned in this documentation, and they are not publically announced by Adobe, please add this warning to attribute/method so the user knows to use it at their own risk.
Warning
This method/property is officially undocumented and was found via research. The information here may be inaccurate, and this whole method/property may disappear or stop working some point. Please contribute if you have more information on it!
!!! warning
This method/property is officially undocumented and was found via research. The information here may be inaccurate, and this whole method/property may disappear or stop working some point. Please contribute if you have more information on it!
Ended: Contributing
Updating Legacy Docs ↵
.rst -> MD Conversion Process¶
- This is a one-time conversion process; it requires changing the Sphinx build system, building as markdown, replacing all the older rst files with the new markdown files, and then going through and cleaning up by hand.
- It is tedious, but the bulk of the work is cleaning vs actual conversion– and we can leverage the existing Sphinx setup.
- This relies on the sphinx_markdown_builder Sphinx plugin.
Tip
It is highly recommended to do this work in a child branch of the repo, vs working directly in main. This will be extremely destructive.
This works in several main phases:
- Setup – installing required systems for the automated conversion
- Convert – running these systems to convert the .rst docs to .md
- Initialize MkDocs – set up the new system that will serve the files
- Text Cleanup – all of the work to turn the converted docs to a final product
- Project Cleanup – removing the legacy build system files
- Deploy
1. Setup¶
First, all work should be done in a new branch. Historically, these have been named change/mkdocs
.
Once the work is done, submit a PR to merge it into the main branch.
Setting up RST -> MD Conversion¶
- Install
sphinx
&sphinx_markdown_builder
(for converting from .rst to .md):pip install sphinx sphinx_markdown_builder
- Update Sphinx config to convert to Markdown
- Navigate to
./docs/conf.py
- Replace all of the contents with only this:
extensions = ["sphinx_markdown_builder"]
- Navigate to
Setting up the new system¶
- Replace all contents of
./requirements.txt
with the following list of dependencies:mkdocs mkdocs-material mkdocs-git-revision-date-localized-plugin mkdocs-print-site-plugin
- Install the above requirements via
pip
:pip install -r requirements.txt
2. Convert¶
- Run the sphinx command to convert the docs
sphinx-build -M markdown ./docs ./build
- This will generate .md files within
./build/markdown
- This will generate .md files within
- We want to replace all of the .rst files with the .md files, however if we simply delete the .rst and add the .md we will lose all of the git history!
- To get around this, we're going to first rename all of the .rst files to .md, and then overwrite the "fake" renamed .md files with the converted .md files
- Using your renamer tool of choice, rename all .rst files in docs/ to the .md extension
- Commit this rename change!
- Be careful not to commit anything in
./build/
, as we don't want these in the repo (yet)
- Be careful not to commit anything in
- Now, overwrite all
./docs/
.md files with those from./build/markdown/
- Delete the
./build/
folder, as it won't be needed - Rename
./docs/index.md
to./docs/_nav.md
- This is a temporary process that we'll resolve later
- It needs to be rewritten in a different format, and moved into
./mkdocs.yml
, with this file deleted
- Commit this overwrite change!
- This solidifies the history, at which point we can start cleanup
3. Initialize MkDocs¶
Instead of initializing MkDocs from scratch, we're going to just copy files over from the After Effects Scripting Guide and tweak those to fit.
- Copy the following files from the above guide into this repo, overwriting if existing:
./.github/
./_static/
./docs/CNAME
./docs/index.md
./overrides/
./.editorconfig
./.gitattributes
./.gitignore
./.mkdocs.yml
- Update anything related to "After Effects Scripting Guide" and make it relevant for this repo
./docs/index.md
./.mkdocs.yml
- Open a terminal to the root folder, and run the below command to serve the docs
mkdocs serve
4. Text Cleanup¶
Bulk Cleanup¶
Search & Replace Steps¶
- Remove generated
<a>
links- Using regex, search for
<a id=".+"></a>(\n|\r)(\n|\r)
and replace with blank
- Using regex, search for
- Update notes, warnings, tips admonitions
- Valid admonitions can be found here
- Using regex, search for
#### NOTE\n(.+)
and replace with!!! note\n $1
- Using regex, search for
#### WARNING\n(.+)
and replace with!!! warning\n $1
- Using regex, search for
#### TIP\n(.+)
and replace with!!! tip\n $1
- Update case-sensitive syntax highlighting languages
- Using regex, search for
```AppleScript
and replace with```applescript
- Using regex, search for
- Replace nonstandard
- Using regex, search for
“|”
and replace with"
- Using regex, search for
‘|’
and replace with'
- Using regex, search for
–
and replace with-
- Search for
…
and replace with...
- Using regex, search for
- Update offset sublist settings
- Using regex, search for
(\n|\r) : -
and replace with:\n -
– only seems to be an issue with changelog
- Using regex, search for
Look for lingering bulk-conversion issues¶
- Search for lines starting with
: -
and - Search for rst-specific syntax such as the below, and fix them as needed
.. note::
::
:ref:
.. WARNING::
Manual Cleanup¶
Sidebar / Navigation¶
The sidebar / navigation needs to be present inside of ./mkdocs.yml
, formatted identically to how it's presented in the After Effects Scripting Guide repo.
Earlier, we set aside ./docs/_nav.md
as a reference point. Now, use that file as the basis for how to display the nav within the nav
section within ./mkdocs.yml
.
When finished, delete ./docs/_nav.md
.
Links¶
- Search for hyphenated cross-links and replace with plain slugs, i.e.
[CharacterRange.pasteFrom()](../text/characterrange.md#characterrange-pastefrom)
to[CharacterRange.pasteFrom()](../text/characterrange.md#characterrangepastefrom)
- This regex search can help, but fails when the link is also a header (see changelog):
(?:#)(.*?)-(.*?)(?:\))
=>#$1$2)
- Note: this also fails for any page that uses hyphens in page names, which is... most of them
- Search for anchored links to the top-level page & replace with direct page link, i.e.
[Settings object](../other/settings.md#settings)
to[Settings object](../other/settings.md)
- This regex search / replace can help:
(.*)\.md#(\1)\)
=>$1.md)
- Search for empty in-page links and replace them with the proper format, i.e.
[app.watchFolder()]()
to[app.watchFolder()](#appwatchfolder)
Update Tables¶
In RST, tables didn't need to have header rows. In markdown, they do (should). This, unfortunately, means a lot of work is needed as the conversion method isn't capable of generating table headers.
Note
We're also going to use this opportunity to add in property types for arguments & parameters, making the docs friendlier to use.
- Set up table headers
- Format tables according to the required table format.
See Style Guide - Tables.
Titles¶
See Style Guide - Title Hierarchy.
Other¶
- Check that images are properly linked to the root
./docs/_static
folder - Value ranges should be formatted as:
`[0.0..10800.0]`
(surrounded by backticks, two periods between min and max) - Sort class properties into "Attributes" and "Methods"
- Alphabetically sort methods and attributes
- Inline doublespace
(?<![\n\r\| ])( ){2,}(?![ \|])
- Bad indent (not a multiple of 4 spaces)
^( ){1,3}(?:(\1)(\1)(\1)(\1))*(?=\S+)
- (based on this stackoverflow answer)
- Remove unnecessary
<br/>
5. Project Cleanup¶
Now that we've got a full suite of .md files, we can remove some old cruft:
./build/
./docs/**/*.rst
./docs/conf.py
./.readthedocs.yaml
./make.bat
./Makefile
6. Open a PR!¶
Once the above steps are complete, it's time to open a PR for review!
Open a new Pull Request for merging the change/mkdocs
branch into the main branch of the repo.
Once reviewed & accepted by an org admin, your converted docs will be pushed into main repo and it'll be time for an org admin to Deploy the docs!
Deploying the Updated Docs¶
Tip
Note that the following guide is only possible for Org admins. If you're stuck at this step, please contact an organization admin to proceed.
Once a conversion-branch PR has been approved & merged into the main repo, it's time to deploy the new docs.
Once the PR has been merged in, the automated build process (from .\github\workflows\ci.yml
) should run, generating a new branch gh-pages
. This is the branch we'll use to generate the hosted page via Github Pages.
Changes in the Repo¶
- Update the
./docs/CNAME
file to reflect the new custom domain (ieae-scripting.docsforadobe.dev
->ai-scripting.docsforadobe.dev
) & ensure this change is committed & pushed- If this isn't committed to the main branch, then every push to the repo (and CI action) will remove this file and lose the custom domain. See this gh-pages issue.
Changes on Github¶
- From the Github repo, set up Pages & have it use this new branch.
Settings
>Pages
> Enable PagesDeploy from a Branch
> Choose the named branch above- For folder, choose "/ (root)"
- Set up the custom domain (
xx.docsforadobe.dev
)- This may already be defined by the above CNAME file, but check here just in case.
- Enable "Enforce HTTPs"
Changes on web host¶
- In the domain registrar / web host, enable DNS-only hosting for this domain
- Add a CNAME record pointing to
docsforadobe.github.io
- Apply for an SSL cert
- Remove any readthedocs.io hooks from the Github repo
- Set up branch permissions to require PRs to the main branch
Changes in readthedocs.io¶
- Remove the legacy docs from readthedocs.io
Conversion Progress¶
This document outlines the current status of converting the existing docs.
- Main docsforadobe.dev site
- AE C++ SDK
- Note: In progress
- AE Expression Reference
- AE Scripting Guide
- AI Scripting Guide
- AME Scripting Guide
- Note: In progress
- Animate Scripting Guide
- ESTK
- Note: In progress
- PPro C++ SDK
- Note: In progress
- PPro Scripting Guide