From 770d1cabba30677f13caf9b701452e390982cc6d Mon Sep 17 00:00:00 2001 From: AdamNaj Date: Wed, 11 Dec 2019 12:55:34 +0100 Subject: [PATCH] # 0.1.1 - More accurate extension descriptions - Improvements to Sitecore extension snippets - Verified and supplemented list of full extensions - More links to documentation in auto-complete tooltips - i_item extensions no longer erroneously appear as available options for fields auto completion. --- .examples/Product Summary.scriban | 27 ++++ .examples/gallery.scriban | 44 ++++--- CHANGELOG.md | 11 +- README.md | 14 +- package.json | 4 +- src/autoCompletion.ts | 21 ++- src/autoCompletionItem.ts | 14 +- src/sitecoreFunctions.ts | 7 - src/sitecoreObjects.ts | 210 ++++++++++++++++++++---------- 9 files changed, 241 insertions(+), 111 deletions(-) create mode 100644 .examples/Product Summary.scriban diff --git a/.examples/Product Summary.scriban b/.examples/Product Summary.scriban new file mode 100644 index 0000000..e5d128d --- /dev/null +++ b/.examples/Product Summary.scriban @@ -0,0 +1,27 @@ +
+ {{ displayName = i_item.display_name | html.escape }} + +
+ {{ + productImage = i_item.images.targets | array.first + if productImage + mediaUrl = productImage.media_url + end + }} + +
+
+ +
\ No newline at end of file diff --git a/.examples/gallery.scriban b/.examples/gallery.scriban index 9099213..608692a 100644 --- a/.examples/gallery.scriban +++ b/.examples/gallery.scriban @@ -1,26 +1,34 @@ -{{- # ↓ Name of the item template -}} -{{ if i_item.template_name == "Gallery Image" }} - - +{{- # ↓ Name of the item template - + if i_item.template_name == "Gallery Image" + sc_editframe i_item 'Gallery Image' -}} + + {{- # ↓ raw value from the field ↓ media url from a field -}} - + {{- # ↓ item.FieldName - renders Sitecore field -}} - {{ i_item.Image }} - - -{{end}} + {{ i_item.Image }} + + + {{ + sc_endeditframe + end}} + +{{- # ↓ conditional statement + if i_item.template_name == "Gallery Video" + sc_editframe i_item 'Gallery Video' + if (i_item.VideoID.raw ) == "" && (i_item.VideoThumbnail.raw) == "" -}} -{{- # ↓ conditional statement }} -{{ if i_item.template_name == "Gallery Video" }} - {{ if (i_item.VideoID.raw ) == "" && (i_item.VideoThumbnail.raw) == "" }} [Edit Gallery Video here] - {{ else }} - - {{- # ↓ access model properties }} + {{- else -}} + + + {{- # ↓ access model properties -}} + {{ i_item.VideoDescription.raw }} - - {{end}} -{{end}} \ No newline at end of file + {{ + end + sc_endeditframe + end }} diff --git a/CHANGELOG.md b/CHANGELOG.md index eaff0e5..9cabac4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ # Change Log -Sitecore Scriban Syntax Coloring and intellisense for known objects Extension for Visual Studio Code +Sitecore Experience Accelerator Scriban syntax coloring and auto completion for known objects - Extension for Visual Studio Code -## 1.0.0 +## 0.1.1 +- More accurate extension descriptions +- Improvements to Sitecore extension snippets +- Verified and supplemented list of full extensions +- More links to documentation in auto-complete tooltips +- i_item extensions no longer erroneously appear as available options for fields auto completion. + +## 0.1.0 - Initial release \ No newline at end of file diff --git a/README.md b/README.md index 52cfd28..a9537ad 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,20 @@ # Scriban Syntax Coloring extension for Visual Studio Code -This extension allows to colorize Scriban scripts and Scriban-Html scripts following the syntax of the [scriban templating language](https://github.com/lunet-io/scriban) +This extension allows to colorize Sitecore Experience Accelerator Scriban-Html scripts following the syntax of the [scriban templating language](https://github.com/lunet-io/scriban) with [SXA extensions](https://doc.sitecore.com/developers/sxa/93/sitecore-experience-accelerator/en/scriban-templates.html) ## Features -- Mixed **scriban and HTML** (using `{{` and `}}` to enter scriban) with the expected file extensions: - - `.scriban` +- Mixed **Scriban and HTML** (using `{{` and `}}` to enter scriban) with the `.scriban` file extension. +- Supports auto complete for Scriban language auto complete including embedded objects. +- Supports auto complete for OOTB Sitecore Experience Accelerator functions and objects. +## 0.1.1 +- More accurate extension descriptions +- Improvements to snippets +- Descriptions synchonized with the documentation +- Verified and supplemented list of full extensions +- More links to documentation in auto-complete tooltips +- i_item extensions no longer erroneously appear as available options for fields auto completion. ## 0.1.0 - Support for mixed `Scriban` and `HTML` grammar diff --git a/package.json b/package.json index 891818a..ccaa0bc 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "sitecore-scriban", "displayName": "Sitecore Scriban", - "description": "Syntax Coloring for Scriban Templating Language with Sitecore Extensions", - "version": "0.1.0", + "description": "Scriban Templates syntax coloring and auto completion for Sitecore Experience Accelerator (SXA)", + "version": "0.1.1", "publisher": "adamnaj", "repository": { "type": "git", diff --git a/src/autoCompletion.ts b/src/autoCompletion.ts index a14633e..6ac5541 100644 --- a/src/autoCompletion.ts +++ b/src/autoCompletion.ts @@ -7,7 +7,7 @@ import { languageObjects } from './languageObjects'; import { methods, embeddedItemCompletions } from './sitecoreObjects'; import { sitecoreFunctions } from './sitecoreFunctions'; import { language } from './languageSyntax'; -import { isInFunctionCompletion, codeBlockFromTemplate, stripFunctionNameFromLine, isInScriban } from './regularExpressions'; +import { isInFunctionCompletion, codeBlockFromTemplate, stripFunctionNameFromLine } from './regularExpressions'; import { snippetCompletion, objectFunctionCompletion } from './autoCompletionItem'; const documentStart = new vscode.Position(0, 0); @@ -55,10 +55,10 @@ export function provideGlobalCompletionItems(document: vscode.TextDocument, posi } // sitecore functions: sc_field, sc_translate ... - snippetCompletion(sitecoreFunctions, linePrefix, results, vscode.CompletionItemKind.Function); + snippetCompletion(sitecoreFunctions, linePrefix, results, vscode.CompletionItemKind.Function, "https://doc.sitecore.com/developers/sxa/93/sitecore-experience-accelerator/en/the-embedded-functions-for-the-scriban-template.html"); //language structures: for, while, if ... - snippetCompletion(language, linePrefix, results, vscode.CompletionItemKind.Snippet); + snippetCompletion(language, linePrefix, results, vscode.CompletionItemKind.Snippet, "https://github.com/lunet-io/scriban/blob/master/doc/language.md"); } return results; @@ -68,7 +68,8 @@ export function provideFunctionCompletionItems(document: vscode.TextDocument, po // all text from beginning of the document to cursor position let documentPrefix = document.getText(new vscode.Range(documentStart, position)) - + const isInScriban = new RegExp(/[{]([^}]+)$/g); + if (!isInScriban.test(documentPrefix)) { return; } @@ -105,7 +106,14 @@ export function provideFunctionCompletionItems(document: vscode.TextDocument, po methods.forEach(element => { var validationRegex = new RegExp(element.validationRegEx); if (validationRegex.test(linePrefix)) { - results.push(objectFunctionCompletion(element.prefix, element.name, element.template, element.description, vscode.CompletionItemKind.Property)) + var description = element.description + if(element.prefix === "i_item."){ + description = description + "... [more](https://doc.sitecore.com/developers/sxa/93/sitecore-experience-accelerator/en/item-and-field-extensions.html)"; + } else { + description = description + "... [more](https://doc.sitecore.com/developers/sxa/93/sitecore-experience-accelerator/en/the-embedded-functions-for-the-scriban-template.html)"; + } + + results.push(objectFunctionCompletion(element.prefix, element.name, element.template, description, vscode.CompletionItemKind.Property)) } }); @@ -116,7 +124,8 @@ export function provideFunctionCompletionItems(document: vscode.TextDocument, po commitCharacterCompletion.kind = vscode.CompletionItemKind.Variable; commitCharacterCompletion.insertText = item.name; commitCharacterCompletion.commitCharacters = ['.']; - commitCharacterCompletion.documentation = new vscode.MarkdownString(item.description); + var description = item.description + "... [more](https://doc.sitecore.com/developers/sxa/93/sitecore-experience-accelerator/en/the-embedded-items-and-objects-in-the-scriban-context.html)"; + commitCharacterCompletion.documentation = new vscode.MarkdownString(description); commitCharacterCompletion.command = { command: 'editor.action.triggerSuggest', title: 'Re-trigger completions...' }; results.push(commitCharacterCompletion); } diff --git a/src/autoCompletionItem.ts b/src/autoCompletionItem.ts index e9a3055..c22b951 100644 --- a/src/autoCompletionItem.ts +++ b/src/autoCompletionItem.ts @@ -2,12 +2,13 @@ * Copyright (C) 2019 - Adam Najmanowicz. All rights reserved. *--------------------------------------------------------*/ - import * as vscode from 'vscode'; +import * as vscode from 'vscode'; import { ScribanSnippet } from './types'; import { getCodeBlockFromSnippet } from './autoCompletion'; -import { isInScriban, lineHasPipe, snippetVariableCleanup } from './regularExpressions'; +import { lineHasPipe, snippetVariableCleanup } from './regularExpressions'; -export function snippetCompletion(snippets: ScribanSnippet[], linePrefix: string, results: vscode.CompletionItem[], kind: vscode.CompletionItemKind) { +export function snippetCompletion(snippets: ScribanSnippet[], linePrefix: string, results: vscode.CompletionItem[], kind: vscode.CompletionItemKind, helpUrl: String) { + const isInScriban = new RegExp(/[{]([^}]+)$/g); for (let snippet of snippets) { const commitCharacterCompletion = new vscode.CompletionItem(snippet.name); commitCharacterCompletion.kind = kind; @@ -24,6 +25,7 @@ export function snippetCompletion(snippets: ScribanSnippet[], linePrefix: string } } + let description = new vscode.MarkdownString(snippet.description+"... [more]("+ helpUrl +")"); if (inMoustaches) { // if inside moustache block {{ }} @@ -33,7 +35,7 @@ export function snippetCompletion(snippets: ScribanSnippet[], linePrefix: string continue; } commitCharacterCompletion.insertText = new vscode.SnippetString(snippet.pipeTemplate + " "); - commitCharacterCompletion.documentation = new vscode.MarkdownString(snippet.description).appendCodeblock(getCodeBlockFromSnippet(snippet.pipeTemplate)).appendCodeblock("\n \n "); // (snippet.pipeCodeBlock); + commitCharacterCompletion.documentation = description.appendCodeblock(getCodeBlockFromSnippet(snippet.pipeTemplate)).appendCodeblock("\n \n "); // (snippet.pipeCodeBlock); } else { // if not after pipe, just within moustaches {{ ... }} //template must be wrapped with moustaches - those are used inside of pure-HTML snippets @@ -47,7 +49,7 @@ export function snippetCompletion(snippets: ScribanSnippet[], linePrefix: string continue; } commitCharacterCompletion.insertText = new vscode.SnippetString(template); - commitCharacterCompletion.documentation = new vscode.MarkdownString(snippet.description).appendCodeblock(getCodeBlockFromSnippet(template)).appendCodeblock("\n \n ") // snippet.codeBlock); + commitCharacterCompletion.documentation = description.appendCodeblock(getCodeBlockFromSnippet(template)).appendCodeblock("\n \n ") // snippet.codeBlock); } } else { @@ -60,7 +62,7 @@ export function snippetCompletion(snippets: ScribanSnippet[], linePrefix: string documentation = getCodeBlockFromSnippet(snippet.template.join("\n"), false); } - commitCharacterCompletion.documentation = new vscode.MarkdownString(snippet.description).appendCodeblock(documentation).appendCodeblock("\n "); // snippet.codeBlock); + commitCharacterCompletion.documentation = description.appendCodeblock(documentation).appendCodeblock("\n "); // snippet.codeBlock); } results.push(commitCharacterCompletion); } diff --git a/src/sitecoreFunctions.ts b/src/sitecoreFunctions.ts index 8d7135b..7e8272f 100644 --- a/src/sitecoreFunctions.ts +++ b/src/sitecoreFunctions.ts @@ -124,11 +124,4 @@ export const sitecoreFunctions = [ "template": "sc_parameter '${1:Parameter Name}'", "pipeTemplate": "sc_parameter", }, - { - "name": "", - "description": "", - "validationRegEx": "", - "template": "", - "pipeTemplate": "", - }, ]; diff --git a/src/sitecoreObjects.ts b/src/sitecoreObjects.ts index 8715ad2..598b75b 100644 --- a/src/sitecoreObjects.ts +++ b/src/sitecoreObjects.ts @@ -11,7 +11,7 @@ export const embeddedItemCompletions = [ { "name": "i_item", "template": "i_item", - "description": "Current Sitecore item in the Rendering Variant pipeline.", + "description": "The current item within the rendering variant context. Often, this is an equivalent to the `i_datasource`.\n\nIf your Scriban template was embedded within a _Query_ or _Reference_ rendering variant field, `i_item` will be exactly the item that other rendering variant fields would use for their rendering process", }, { "name": "i_site", @@ -61,182 +61,258 @@ export const methods = "name": "...", "template": "", "prefix": "i_item.", - "validationRegEx": "(i_[\\w.]*)$", - "description": "Type the name of the field to use it. (cannot contain spaces)", - }, - { - "name": "template_name", - "template": "template_name", - "prefix": "i_item.", - "validationRegEx": "(i_[\\w.]*)$", - "description": "", + "validationRegEx": "(i_[\\w]*[.])$", + "description": "Name of the field to render. (if the field name contains spaces or special characters use `sc_field` function instead)", }, { "name": "children", "template": "children", "prefix": "i_item.", - "validationRegEx": "(i_[\\w.]*)$", - "description": "", + "validationRegEx": "(i_[\\w]*[.])$", + "description": "Returns the children of the item as an `Item` list", }, { - "name": "parent", - "template": "parent", + "name": "display_name", + "template": "display_name", "prefix": "i_item.", - "validationRegEx": "(i_[\\w.]*)$", - "description": "", + "validationRegEx": "(i_[\\w]*[.])$", + "description": "Returns the `Display Name` of the item", }, { - "name": "template_id", - "template": "template_id", + "name": "id", + "template": "id", "prefix": "i_item.", - "validationRegEx": "(i_[\\w.]*)$", - "description": "", + "validationRegEx": "(i_[\\w]*[.])$", + "description": "Returns the `ID` of the item", }, { - "name": "version", - "template": "version", + "name": "has_children", + "template": "has_children", "prefix": "i_item.", - "validationRegEx": "(i_[\\w.]*)$", - "description": "", + "validationRegEx": "(i_[\\w]*[.])$", + "description": "Returns `true` if the item has children", }, { - "name": "path", - "template": "path", + "name": "has_layout", + "template": "has_layout", "prefix": "i_item.", - "validationRegEx": "(i_[\\w.]*)$", - "description": "", + "validationRegEx": "(i_[\\w]*[.])$", + "description": "Returns `true` if the item has layout", }, { "name": "language", "template": "language", "prefix": "i_item.", - "validationRegEx": "(i_[\\w.]*)$", - "description": "", + "validationRegEx": "(i_[\\w]*[.])$", + "description": "Returns the language code of the item", }, { - "name": "has_children", - "template": "has_children", + "name": "media_url", + "template": "media_url", "prefix": "i_item.", - "validationRegEx": "(i_[\\w.]*)$", - "description": "", + "validationRegEx": "(i_[\\w]*[.])$", + "description": "Returns the media URL to the item", }, { - "name": "display_name", - "template": "display_name", + "name": "name", + "template": "name", "prefix": "i_item.", - "validationRegEx": "(i_[\\w.]*)$", - "description": "", + "validationRegEx": "(i_[\\w]*[.])$", + "description": "Returns the `Name` of the item", }, { - "name": "name", - "template": "name", + "name": "parent", + "template": "parent", "prefix": "i_item.", - "validationRegEx": "(i_[\\w.]*)$", - "description": "", + "validationRegEx": "(i_[\\w]*[.])$", + "description": "Returns parent of the item as an `Item` object", + }, + { + "name": "path", + "template": "path", + "prefix": "i_item.", + "validationRegEx": "(i_[\\w]*[.])$", + "description": "Returns the path of the item", + }, + { + "name": "template_id", + "template": "template_id", + "prefix": "i_item.", + "validationRegEx": "(i_[\\w]*[.])$", + "description": "Returns the ID of the item template as a `string` object", + }, + { + "name": "template_name", + "template": "template_name", + "prefix": "i_item.", + "validationRegEx": "(i_[\\w]*[.])$", + "description": "Returns the name of the item template as a `string` object", }, { "name": "url", "template": "url", "prefix": "i_item.", - "validationRegEx": "(i_[\\w.]*)$", - "description": "", + "validationRegEx": "(i_[\\w]*[.])$", + "description": "Returns the URL to the item using the site `LinkProvider`", }, { - "name": "media_url", - "template": "media_url", + "name": "version", + "template": "version", "prefix": "i_item.", - "validationRegEx": "(i_[\\w.]*)$", - "description": "", + "validationRegEx": "(i_[\\w]*[.])$", + "description": "Returns the version number of the item", }, + + + + + { "name": "raw", "template": "raw", "prefix": "i_item.field.", "validationRegEx": "(i_\\w*\\.\\w*\\.[\\w\\.]*)$", - "description": "", + "description": "Returns the raw value of a field. For example, to render an ID to an item that you use in your JavaScript or for buttons that should not be editable", }, { "name": "target", "template": "target", "prefix": "i_item.field.", "validationRegEx": "(i_\\w*\\.\\w*\\.[\\w\\.]*)$", - "description": "", + "description": "Returns an item selected in a field that can store links to items. If the field can contain links to multiple items, the first item in the list is returned. If the field is empty, the function returns a null value", }, { "name": "targets", "template": "targets", "prefix": "i_item.field.", "validationRegEx": "(i_\\w*\\.\\w*\\.[\\w\\.]*)$", - "description": "", + "description": "Returns an array of items selected in a field that can store links to items. If the field is empty, the function returns an empty list", }, + + + + + { "name": "is_debugging", "template": "is_debugging", "prefix": "o_pagemode.", "validationRegEx": "(o_pagemode\\.[\\w]*)$", - "description": "", + "description": "Returns `True' if the page is rendered in debug mode", }, { "name": "is_experience_editor", "template": "is_experience_editor", "prefix": "o_pagemode.", "validationRegEx": "(o_pagemode\\.[\\w]*)$", - "description": "", - }, - { - "name": "is_experience_editor", - "template": "is_experience_editor", - "prefix": "o_pagemode.", - "validationRegEx": "(o_pagemode\\.[\\w]*)$", - "description": "", + "description": "Returns `True' if the page is rendered within Experience Editor", }, { "name": "is_experience_editor_editing", "template": "is_experience_editor_editing", "prefix": "o_pagemode.", "validationRegEx": "(o_pagemode\\.[\\w]*)$", - "description": "", + "description": "Returns `True' if the page is rendered within Experience Editor in Edit mode", }, { "name": "is_normal", "template": "is_normal", "prefix": "o_pagemode.", "validationRegEx": "(o_pagemode\\.[\\w]*)$", - "description": "", + "description": "Returns `True' if the page is rendered for a visitor", }, { "name": "is_preview", "template": "is_preview", "prefix": "o_pagemode.", "validationRegEx": "(o_pagemode\\.[\\w]*)$", - "description": "", + "description": "Returns `True' if the page is rendered within Experience Editor in Preview mode", }, { "name": "is_simulated_device_previewing", "template": "is_simulated_device_previewing", "prefix": "o_pagemode.", "validationRegEx": "(o_pagemode\\.[\\w]*)$", - "description": "", + "description": "Returns `True' if the page is rendered within Experience Editor in Simulated Preview mode", }, { "name": "is_profiling", "template": "is_profiling", "prefix": "o_pagemode.", "validationRegEx": "(o_pagemode\\.[\\w]*)$", - "description": "", + "description": "Returns `True' if the page is rendered with profiling information", }, + + + + + { "name": "is_administrator", "template": "is_administrator", "prefix": "o_context.", "validationRegEx": "(o_context\\.[\\w]*)$", - "description": "", + "description": "Returns `True' if the current user is an administrator", }, { "name": "user", "template": "user", "prefix": "o_context.", "validationRegEx": "(o_context\\.[\\w]*)$", - "description": "", + "description": "User in whose context the request is performed", + }, + { + "name": "domain", + "template": "domain", + "prefix": "o_context.", + "validationRegEx": "(o_context\\.[\\w]*)$", + "description": "Domain of the user in whose context the request is performed", + }, + { + "name": "database", + "template": "database", + "prefix": "o_context.", + "validationRegEx": "(o_context\\.[\\w]*)$", + "description": "Database from which the request sources the data", + }, + + + + + + { + "name": "poi_type_id", + "template": "poi_type_id", + "prefix": "o_geospatial.", + "validationRegEx": "(o_geospatial\\.[\\w]*)$", + "description": "Guid of the POI type", + }, + { + "name": "poi_icon", + "template": "poi_icon", + "prefix": "o_geospatial.", + "validationRegEx": "(o_geospatial\\.[\\w]*)$", + "description": "POI icon URL", + }, + { + "name": "latitude", + "template": "latitude", + "prefix": "o_geospatial.", + "validationRegEx": "(o_geospatial\\.[\\w]*)$", + "description": "Latitude of the POI that is rendered", + }, + { + "name": "longitude", + "template": "longitude", + "prefix": "o_geospatial.", + "validationRegEx": "(o_geospatial\\.[\\w]*)$", + "description": "Longitude of the POI that is rendered", + }, + { + "name": "unit", + "template": "unit", + "prefix": "o_geospatial.", + "validationRegEx": "(o_geospatial\\.[\\w]*)$", + "description": "Kilometers, miles", }, ];