-
Notifications
You must be signed in to change notification settings - Fork 132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for custom scripts #1056
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -90,6 +90,9 @@ public struct DocumentationBundle { | |
/// A custom JSON settings file used to theme renderer output. | ||
public let themeSettings: URL? | ||
|
||
/// A custom JSON settings file used to add custom scripts to the renderer output. | ||
public let customScripts: URL? | ||
|
||
/** | ||
A URL prefix to be appended to the relative presentation URL. | ||
|
||
|
@@ -108,6 +111,7 @@ public struct DocumentationBundle { | |
/// - customHeader: A custom HTML file to use as the header for rendered output. | ||
/// - customFooter: A custom HTML file to use as the footer for rendered output. | ||
/// - themeSettings: A custom JSON settings file used to theme renderer output. | ||
/// - customScripts: A custom JSON settings file used to add custom scripts to the renderer output. | ||
public init( | ||
info: Info, | ||
baseURL: URL = URL(string: "/")!, | ||
|
@@ -116,7 +120,8 @@ public struct DocumentationBundle { | |
miscResourceURLs: [URL], | ||
customHeader: URL? = nil, | ||
customFooter: URL? = nil, | ||
themeSettings: URL? = nil | ||
themeSettings: URL? = nil, | ||
customScripts: URL? = nil | ||
) { | ||
self.info = info | ||
self.baseURL = baseURL | ||
|
@@ -126,29 +131,14 @@ public struct DocumentationBundle { | |
self.customHeader = customHeader | ||
self.customFooter = customFooter | ||
self.themeSettings = themeSettings | ||
self.customScripts = customScripts | ||
self.rootReference = ResolvedTopicReference(bundleIdentifier: info.identifier, path: "/", sourceLanguage: .swift) | ||
self.documentationRootReference = ResolvedTopicReference(bundleIdentifier: info.identifier, path: NodeURLGenerator.Path.documentationFolder, sourceLanguage: .swift) | ||
self.tutorialsRootReference = ResolvedTopicReference(bundleIdentifier: info.identifier, path: NodeURLGenerator.Path.tutorialsFolder, sourceLanguage: .swift) | ||
self.technologyTutorialsRootReference = tutorialsRootReference.appendingPath(urlReadablePath(info.displayName)) | ||
self.articlesDocumentationRootReference = documentationRootReference.appendingPath(urlReadablePath(info.displayName)) | ||
} | ||
|
||
@available(*, deprecated, renamed: "init(info:baseURL:symbolGraphURLs:markupURLs:miscResourceURLs:customHeader:customFooter:themeSettings:)", message: "Use 'init(info:baseURL:symbolGraphURLs:markupURLs:miscResourceURLs:customHeader:customFooter:themeSettings:)' instead. This deprecated API will be removed after 6.1 is released") | ||
public init( | ||
info: Info, | ||
baseURL: URL = URL(string: "/")!, | ||
attributedCodeListings: [String: AttributedCodeListing] = [:], | ||
symbolGraphURLs: [URL], | ||
markupURLs: [URL], | ||
miscResourceURLs: [URL], | ||
customHeader: URL? = nil, | ||
customFooter: URL? = nil, | ||
themeSettings: URL? = nil | ||
) { | ||
self.init(info: info, baseURL: baseURL, symbolGraphURLs: symbolGraphURLs, markupURLs: markupURLs, miscResourceURLs: miscResourceURLs, customHeader: customHeader, customFooter: customFooter, themeSettings: themeSettings) | ||
self.attributedCodeListings = attributedCodeListings | ||
} | ||
|
||
Comment on lines
-136
to
-151
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a source breaking change. Like the deprecation message says; we can't remove this until after 6.1 is released. See the "Introducing source breaking changes" section of the contributions guidelines |
||
public private(set) var rootReference: ResolvedTopicReference | ||
|
||
/// Default path to resolve symbol links. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1649,6 +1649,7 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate { | |
|
||
private static let supportedImageExtensions: Set<String> = ["png", "jpg", "jpeg", "svg", "gif"] | ||
private static let supportedVideoExtensions: Set<String> = ["mov", "mp4"] | ||
private static let supportedScriptExtensions: Set<String> = ["js"] | ||
|
||
// TODO: Move this functionality to ``DocumentationBundleFileTypes`` (rdar://68156425). | ||
|
||
|
@@ -1729,6 +1730,14 @@ public class DocumentationContext: DocumentationContextDataProviderDelegate { | |
public func registeredDownloadsAssets(forBundleID bundleIdentifier: BundleIdentifier) -> [DataAsset] { | ||
return registeredAssets(inContexts: [DataAsset.Context.download], forBundleID: bundleIdentifier) | ||
} | ||
|
||
/// Returns a list of all the custom scripts that registered for a given `bundleIdentifier`. | ||
/// | ||
/// - Parameter bundleIdentifier: The identifier of the bundle to return download assets for. | ||
/// - Returns: A list of all the custom scripts for the given bundle. | ||
public func registeredCustomScripts(forBundleID bundleIdentifier: BundleIdentifier) -> [DataAsset] { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would prefer if this was |
||
return registeredAssets(withExtensions: DocumentationContext.supportedScriptExtensions, forBundleID: bundleIdentifier) | ||
} | ||
|
||
typealias Articles = [DocumentationContext.SemanticResult<Article>] | ||
private typealias ArticlesTuple = (articles: Articles, rootPageArticles: Articles) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FYI, the method of input discovery in this file is about to be deprecated in #1059 and won't be used by DocC anymore. These same changes need to be implemented in DocumentationContext.InputProvider which is what DocC will use to discover its inputs after #1057 lands. It would also be good to update |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
{ | ||
"openapi": "3.0.0", | ||
"info": { | ||
"title": "Custom Scripts", | ||
"description": "This spec describes the permissible contents of a custom-scripts.json file in a documentation catalog, which is used to add custom scripts to a DocC-generated website.", | ||
"version": "0.0.1" | ||
}, | ||
"paths": {}, | ||
"components": { | ||
"schemas": { | ||
"Scripts": { | ||
"type": "array", | ||
"description": "An array of custom scripts, which is the top-level container in a custom-scripts.json file.", | ||
"items": { | ||
"oneOf": [ | ||
{ "$ref": "#/components/schemas/ExternalScript" }, | ||
{ "$ref": "#/components/schemas/LocalScript" }, | ||
{ "$ref": "#/components/schemas/InlineScript" } | ||
] | ||
} | ||
}, | ||
"Script": { | ||
"type": "object", | ||
"description": "An abstract schema representing any script, from which all three script types inherit.", | ||
"properties": { | ||
"type": { | ||
"type": "string", | ||
"description": "The `type` attribute of the HTML script element." | ||
}, | ||
"run": { | ||
"type": "string", | ||
"enum": ["on-load", "on-navigate", "on-load-and-navigate"], | ||
"description": "Whether the custom script should be run only on the initial page load, each time the reader navigates after the initial page load, or both." | ||
} | ||
} | ||
}, | ||
"ScriptFromFile": { | ||
"description": "An abstract schema representing a script from an external or local file; that is, not an inline script.", | ||
"allOf": [ | ||
{ "$ref": "#/components/schemas/Script" }, | ||
{ | ||
"properties": { | ||
"async": { "type": "boolean" }, | ||
"defer": { "type": "boolean" }, | ||
"integrity": { "type": "string" }, | ||
} | ||
} | ||
] | ||
}, | ||
"ExternalScript": { | ||
"description": "A script at an external URL.", | ||
"allOf": [ | ||
{ "$ref": "#/components/schemas/ScriptFromFile" }, | ||
{ | ||
"required": ["url"], | ||
"properties": { | ||
"url": { "type": "string" } | ||
} | ||
} | ||
] | ||
}, | ||
"LocalScript": { | ||
"description": "A script from a local file.", | ||
"allOf": [ | ||
{ "$ref": "#/components/schemas/ScriptFromFile" }, | ||
{ | ||
"required": ["name"], | ||
"properties": { | ||
"name": { | ||
"type": "string", | ||
"description": "The name of the local script file, optionally including the '.js' extension." | ||
}, | ||
} | ||
} | ||
] | ||
}, | ||
"InlineScript": { | ||
"description": "A script whose source code is in the custom-scripts.json file itself.", | ||
"allOf": [ | ||
{ "$ref": "#/components/schemas/Script" }, | ||
{ | ||
"required": ["code"], | ||
"properties": { | ||
"code": { | ||
"type": "string", | ||
"description": "The source code of the inline script." | ||
} | ||
} | ||
} | ||
] | ||
} | ||
}, | ||
"requestBodies": {}, | ||
"securitySchemes": {}, | ||
"links": {}, | ||
"callbacks": {} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3251,6 +3251,7 @@ class ConvertActionTests: XCTestCase { | |
|
||
XCTAssertEqual(fileSystem.dump(subHierarchyFrom: targetURL.path), """ | ||
Output.doccarchive/ | ||
├─ custom-scripts/ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Question: is it expected that we create this folder even if the user didn't pass any custom scripts? |
||
├─ data/ | ||
│ ╰─ documentation/ | ||
│ ╰─ something.json | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FIY: Since the name of the replacement changed with the new parameter you may need to update the
renamed
portion of this deprecation annotation. Even if it's not needed, it's nice to do it since it enables the fixit for any code that still uses the deprecated API.