@salespreso/slide-tools
v1.2.2
Published
some scripts to help manage the creation of new slides and sections
Downloads
11
Keywords
Readme
SLIDE TOOLS
Installation
When using slide-tools as a part of your content development workflow.
- check out your chosen LivePreso deck
- run
yarn add -D @salespreso/slide-tools
Development
When upgrading and adding new features to the slide-tools project.
- check out the project to a location of your choice
- run
yarn
- run
yarn link
- open the LivePreso deck directory you wish to test against
- run
yarn link "@salespreso/slide-tools"
Contents
add_slide
and add_section
These commands use inquirer.js to build a series of questions to be answered by the user in order to create a section or slide.
Some questions, such as slide or section ID, where within a section a slide should be inserted, are always asked. The user inputs are assembled in an object. For a new slide they look like this:
{ sectionId: 'property_journey_rent',
insertIndex: 2,
slideId: 'dave',
slideTitle: 'Dave',
template: 'columns'
}
Because inquirer.js takes a plain JS object as the configuration for its series of prompts / questions, a given template can request template-specific questions by defining a JSON file (parameters.json
) in its template root. This can then generate an extended, template-specific series of values for the the template to utilise.
For instance, the columns
template needs to know the column setup for the slide (how many columns, the width of each etc). When the addslide
command is added, and a columns
template selected, a second data object is created.
{ classes: ['collapsed', 'animated'],
height: 'column-group--height-half',
columns:
[
{ width: '1', uid: 'frank', bg_colour: '' },
{ width: '2', uid: 'charlie', bg_colour: 'l-grey-50' }
]
}
templates
Templates are done using lodash / underscores tags. When the template is supplied with specific vars, the slideId
& slideTitle
from the global options are included, to do fundamentals like the scss selector for the slide.
In order to cleanly guard against undefined variables in the template's variable scope (which can cause exceptions), all vars are scoped under a 'data' variable. So a simple template tag looks like this:
<%= data.slideTitle %>
In the columns
template case, the template contains a loop to generate columns. It also has a need to know the total number of columns, in order to define which class to apply to the grid as a whole, for column widths. Instead of asking up front, for this value, it can be calculated within the template, using plain JS:
<% columnTotal=0;
for (var i = 0; i < data.columns.length; ++i) {
columnTotal+=parseInt(data.columns[i].width);
}
%>
configuration and prompt types
Inquirer.js ships with a number of predefined prompt types. I've added 3 third-party extensions to those on offer. One of these (inquirer-select-line) is used in the core configuration, to determine where a slide is inserted in the section's slide sequence. The others are loaded only so that they can be utilised by individual templates. If there is a specific need for additional 3rd party prompts, we can add a require()
statement for it in the script, to make it available.
- inquirer-autocomplete-prompt
- inquirer-recursive - allows you to ask the same set of questions several times
usage
these instructions may change depending on how the tools are ultimately packaged
The tools shoud be run from the project root. If the project.yaml
is not found in the cwd, the script will exit.
node ./slide_tools/slide_tools.js [command]
Where command is one of addsection
or add_slide
.
The addsection
command exposes the entered section ID and section title as slideId
and slideTitle
to the template. This allows slide & section templates to be used interchangeably (unsure if there is value in this).
percent
under the hood
Various checks are currently performed.
- if the section ID to be created already exists, the script will exit
- if a given slide ID already exists (or a folder with that ID exists), the script will exit
- there is currently no check for global uniqueness for slide IDs (as required by imposter); this could easily be added.
Once the checks pass
- the template directory is copied to its destination
- the
parameters.json
removed, if it exists - the files found (index.html or index.njk, slide.scss) there are loaded, the templates run, and the result is written back to the same file.
add_editable_ids
This command uses shortid.js to add unique keys to HTML elements tagged with the data-companywide-editable
and data-companywide-editable-image
tags. The script looks for article
tags in each index.html
to determine the slide's id, and creates keys with the form:
data-companywide-...="[slide_id]_editable_[shortid]"
The keys will only be added to the companywide
attribute if there isn't one already, so you can run this multiple times on the same project and it won't clobber your old keys.
export_deck
command
Run from the project root, it can be used to create a child deck from the current one, in a unique dir, ready for upload.
Takes the following switches
-d <targetdir>
destination dir for the place you are exporting tool-y <child.yaml>
a unqiue yaml file for this deck
The child.yaml
only needs 2 keys - key
and sections
. The child.yaml
is merged with the project.yaml
using _.default()
, so the potential exists to have other child-unique keys, such as hooks
.
When run, the script reads the project.yaml
and child.yaml
, creates the target directory, copies the dist
directory and creates a new merged project.yaml
inside it (as well as an empty src
directory).
The resulting output directory can then be loaded into the CDK and uploaded, under its own unique key.
Examples:
slide_tools export_deck -d ../product-showcase -y product-showcase.yaml
This example creates/replaces a directory one level back call "product-showcase" based on the child project yaml requirements specified in "product-showcase.yaml".
Migrating slides
If a slide exists in the child.yaml
but is not found in the corresponding section of the source yaml, then it will searched for by key, and migrated from elsewhere in the source deck, if found. If it is not found, the script will exit.
If a section exists in the target deck, but not the source, an error will be thrown (as the resulting section will be missing a title slide).
templates
A child yaml's sections and slides can specify if they wish to use a slide from the parent.yaml as a template. This is done by adding meta_template
to the desired section/slide with a path
of section_key/slide_key to declare which section/slide you wish to use as the template. Templated slides in the child.yaml will then be built out by copying over the specified templates.
slides
If no slides are declared for a section using a template, the template section's slides will be copied over to along with the rest of the section's files. If slides are specified for a section using a template, these will be used instead of the template section's slides. In order to omit slides from a section using a template, you will need to declare an empty array.
tags
Similar to a section's slides, if no tags are specified for a child.yaml section/slide using a template, they will receive the template's tags. If tags are declared, none of the template section/slide's tags will be copied over. If you do not wish for any tags to be applied to the resulting section/slide, you must declare an empty array.
variables
Any occurances of the template section/slide's key or title in the index.html, slide.css, slide.js or svgs of the desintation slide will be replaced by the key and title of the section/slide as declared in the child.yaml.
If the template section's slides are in use, the section's key and title will also flow through to the generated slides. Both the section key/title and slide key/title can be declared in a template section's slides, and will be replaced accordingly in these use-cases.
Additional vars can be specified using meta_template.vars
.
Example
parent.yaml
...
sections:
-
key: introduction
title: Introduction
slides:
- { key: standard_slide, title: Standard slide }
-
key: template_divider_section
title: Section (template)
slides:
- { key: template_performance_slide, title: Performance Slide (template) }
- { key: template_stats_slide, title: Stats Slide (template) }
child.yaml
...
sections:
-
key: introduction
title: Introduction
slides:
- { key: standard_slide, title: Standard slide }
-
key: malvern_office
title: Malvern Office
meta_template:
path: template_divider_section
# No slides have been specified, slides will be generated
# using slides included in the template section
-
key: kew_office
title: Kew Office
meta_template:
path: template_divider_section
slides:
-
key: kew_performance
title: Kew Performance
meta_template:
path: template_performance_slide
# Slides have been specified, this will be used instead of the
# section template's slides
-
key: prahran_office
title: Prahran Office
meta_template:
path: template_divider_section
slides: []
# No slides will be included in this section
-
key: malvern_office
key: malvern_office
title: Malvern Office
meta_template:
path: template_divider_section
vars:
occupants: 10
cost: 150
# Any occurances of these var keys in the template_divider_section
# will be replaced with these values when the child deck is built out
Example:
child.yaml
...
sections:
-
key: malvern_office
key: malvern_office
title: Malvern Office
meta_template:
path: template_divider_section
vars:
occupants: 10
cost: 150
# Any occurances of these var keys in the template_divider_section
# will be replaced with these values when the child deck is built out
import_state
command
allow you to inject a full set of feeds and a context into the CDK application, based on either a onlinepreso invite link, or a file generated within the App itself.
usage
from a url
slide_tools import_state --title="New Test Feed Name" --url=<your preso url>
- import from a preso URL. IN this case the URL is parsed and /bundle
is added to put the configuration of the presentation.
from a file
slide_tools import_state --title="New Test Feed Name" --file=<file path>
- import from a file exported from the app. The format of a file for import is a simple json object with context
and feeds
top level keys. A sample export script, that can be pasted into the console of the App, is as follows;
var extractDataTo = function(fileName) {
var comboBlob = { feeds: Bridge.Feed.feeds, context: Bridge.Context.getDict()};
var fs = nw.require("fs");
var path = nw.require("path");
var os = nw.require("os");
var outputFile = path.resolve(os.homedir(), fileName);
fs.writeFileSync(outputFile, JSON.stringify(comboBlob, null, 2));
};
Calling the above with extractDataTo("output.json");
will create output.json
in the root of the user's home directory.
import_state
will not overwrite the existing feeds.json
and context.json
files in your project's data directory, unless you explicitly use the --execute
switch. Without it, the script will generate a pair of new JSON files taht you can compare to the originals, and then replace if you are happy. This behaviour is a safeguard while any bugs are worked out. When --execute
is specified, a feeds.json.bak
will be saved to allow rollback to the previous state.
earlier notes
On next running gulp, you may see a nunjucks error, but it's not in the generated output, I think nunjucks is trying to compile the raw templates (with underscores tags in them). The selector for *.njk
files needs to be tightened to only include those in src
Copying the slide_tools
and templates
folder across to a fresh project, and then creating / editing templates to suit, will allow the code to be recycled; ultimately, it should be wound in to the gulp tasks, as there's nothing here that's project specific. Would just need a few more checks / warnings to make sure the template directories existed.