Differences

This shows you the differences between two versions of the page.

Link to this comparison view

ttg_ce2_publisher_tokens [2012/12/20 04:27] (current)
matthew created
Line 1: Line 1:
 +====== Metadata Tokens ======
  
 +When creating a gallery via the Web module, the Image Info control pane allows the photographer to output image metadata to various outlets in the gallery page. The Image Info control pane:
 +
 +{{http://ce3wiki.theturninggate.net/lib/exe/fetch.php?media=wiki:image-info-ui.png?nolink|}}
 +
 +Generally, this allows the photographer to control the content of image captions and titles, and metadata appearing on the gallery's thumbnail grid.
 +
 +Publisher templates also support a number of metadata outlets, typically mirroring those in "traditional" image galleries exported from the Web module. However, the publisher is unable to access the data formatting information from the Image Info panel. Therefore, TTG galleries support a dedicated set of controls and metadata tokens which may be used to determine metadata data source and formatting within your published galleries. These controls are found in the Output Settings control panel, and look like this:
 +
 +{{http://ce3wiki.theturninggate.net/lib/exe/fetch.php?media=wiki:metadata-tokens-input.png?nolink|}}
 +
 +Metadata tokens offer the ability to create template presets for constructing titles, captions, etc. used for the exported photos. They're designed to allow you to combine photo metadata with your custom text on a per-image basis. Our token system is based largely on [[http://regex.info/blog/lightroom-goodies/template|work done by Jeffrey Friedl]] for his Lightroom export plugins, used with permission. This means that users may work with a common metadata vocabulary in both TTG Publisher and Jeffrey's export plugins.
 +
 +The rest of this page documents the template notation as it exists for the latest version of the publisher. As much as possible, we are mirroring Jeffrey's documentation, making changes where necessary to reflect current Publisher support.
 +
 +----
 +
 +A template is a combination of prose and special tokens wrapped in { ... } that insert photo-specific items.
 +
 +For example, the template
 +
 +''%%Copyright {YYYY} {Artist}%%''
 +
 +includes the text "Copyright", a space, the token ''%%YYYY%%'' (which stands for the year that the photo was taken), a space, and the ''%%Artist%%'' token (which stands for the value of the "Artist" metadata item).
 +
 +For one of my photos taken in 2012, this example would become:
 +
 +Copyright 2012 Matthew Campagna
 +
 +A list of supported tokens follows.
 +
 +===== Photo Date =====
 +
 +| YYYY | The year the photo was taken, as a four-digit string |
 +| YY | The year the photo was taken, as a two-digit string |
 +| MM | The month the photo was taken, as a two-digit string |
 +| DD | The day of the month the photo was taken, as a two-digit string |
 +| HH | The hour value for the time the photo was taken, in 24-hour notation, as a two-digit string |
 +| MIN | The minute value for the time the photo was taken, as a two-digit string |
 +| SS | The seconds value for the time the photo was taken, as a two-digit string |
 +| Mon | The month the photo was taken, as a localized three-character string |
 +| Month | The month the photo was taken, as a localized string |
 +| Date | The day of the month the photo was taken, as one- or two-digit string |
 +| D1 | The full date of the photo, in the system-localized short format that you can set in your operating system's preferences dialog. On my system this is something along the lines of "2010-03-24". Available only in Lr3 or later. |
 +| D2 | The full date of the photo, in the system-localized medium format that you can set in your operating system's preferences dialog. On my system this is something along the lines of "Mar 24, 2010". Available only in Lr3 or later. |
 +| D3 | The full date of the photo, in the system-localized long format that you can set in your operating system's preferences dialog. On my system this is something along the lines of "March 24, 2010". Available only in Lr3 or later. |
 +| T1 | The full time-of-day of the photo, in the system-localized short format that you can set in your operating system's preferences dialog. On my system this is something along the lines of "3:38 PM". Available only in Lr3 or later. |
 +| T2 | The full time-of-day of the photo, in the system-localized long format that you can set in your operating system's preferences dialog. On my system this is something along the lines of "3:38:02 PM". Available only in Lr3 or later. |
 +| PhotoDaysSince=date | The number of days from the given date and the date of the photo. This is intended for use along the lines of "My 2010 In Photos: Day {PhotoDaysSince=2009-12-31}". |
 +| ::: | The date argument is in the form "YYYY-MM-DD" but may also have an appended time, in HH:MM 24-hour notation, to delimit when dates start. If you're a night-owl who might want to include a photo taken late in the evening, after midnight, as being part of the previous day, you might want to use something like "My 2010 In Photos: Day {PhotoDaysSince=2009-12-31 04:00}" to have photo taken until 4am be considered part of the previous day. |
 +| ::: | One concern to watch out for with this date/time example is that photos taken during the first four hours of Jan 1 2010 would appear to still be part of the previous day, day "0". |
 +| PhotoDaysUntil=date | Like PhotoDaysSince, but in the counting-down-until sense. |
 +
 +===== Current Date =====
 +
 +| yyyy | The current year as a four-digit string |
 +| yy | The current year as a two-digit string |
 +| mm | The current month as a two-digit string |
 +| dd | The current day of the month as a two-digit string |
 +| hh | The current hour value, as a two-digit string |
 +| min | The current minute value, as a two-digit string |
 +| ss | The current seconds value, as a two-digit string |
 +| mon | The current month, as a localized three-character string |
 +| month | The current month, as a localized string |
 +| date | The current day of the month, as one- or two-digit string |
 +| d1 | The current full date, in the system-localized short format that you can set in your operating system's preferences dialog. On my system this is something along the lines of "2010-03-23". Available only in Lr3 or later. |
 +| d2 | The current full date, in the system-localized medium format that you can set in your operating system's preferences dialog. On my system this is something along the lines of "Mar 23, 2010". Available only in Lr3 or later. |
 +| d3 | The current full date, in the system-localized long format that you can set in your operating system's preferences dialog. On my system this is something along the lines of "March 23, 2010". Available only in Lr3 or later. |
 +| t1 | The current full time-of-day, in the system-localized short format that you can set in your operating system's preferences dialog. On my system this is something along the lines of "3:38 PM". Available only in Lr3 or later. |
 +| t2 | The current full time-of-day, in the system-localized long format that you can set in your operating system's preferences dialog. On my system this is something along the lines of "3:38:02 PM". Available only in Lr3 or later. |
 +| DaysSince=date | Like PhotoDaysSince, but measures the current date to the date (or date/time) given in the argument, without regard to any photo date. You might want to use this along with something like "My 2010 In Photos: Day {DaysSince=2009-12-31}" if you want to have the Day counter refer to when you do the upload, not when you took the shot. With this token, you'd want to use the date/time form if you're a night owl and want an upload done late in the evening, after midnight, to be considered as having been done the previous day. |
 +| DaysUntil=date | Like PhotoDaysUntil, but in the counting-down-until sense. |
 +
 +===== File Names and Paths =====
 +
 +| Filename | The filename – without path and without extension – of the exported copy |
 +| FILENAME | Like Filename, but includes the extension |
 +| LibraryFilename | The filename – without path and without extension – of the master file in the library (which is not necessarily the filename being generated for the exported copy) |
 +| LIBRARYFILENAME | Like LibraryFilename, but includes the extension |
 +| Folder | The name of the folder (without path) in which the master image in the catalog resides |
 +| Path | The full path of the folder in which the master image in the catalog resides |
 +
 +===== Image =====
 +
 +| Filetype | One of: "JPEG", "RAW", "DNG", "TIFF", "PSD", "DNG", or "Video" |
 +| OriginalWidth | The width of the (possibly pre-crop) original master image (not the exported one), in pixels |
 +| OriginalHeight | The height of the (possibly pre-crop) original master image (not the exported one), in pixels |
 +| Cropped | Either "cropped" or "uncropped". |
 +| CroppedWidth | The width of the (possibly post-crop) library image (not the exported one), in pixels |
 +| CroppedHeight | The height of the (possibly post-crop) library image (not the exported one), in pixels |
 +| AspectRatio | This becomes "Portrait" if the cropped image is more tall than wide, "Square" if the cropped with and height are the same, and "Landscape" if wider than tall. You can substitute your own phrases for each by using the form {AspectRatio=X,Y,Z}, where X, Y, and Z are used for Portrait, Square, and Landscape, respectively. |
 +
 +===== Lens / Camera / Exposure =====
 +
 +| Aperture | The photo's aperture value, formatted like "f/4.5" |
 +| ApertureNum | The photo's aperture value, as a raw number |
 +| CameraMake | The photo's "Make" metadata item in Lightroom's database. |
 +| CameraModel | The photo's "Model" metadata item in Lightroom's database. |
 +| CameraSerialNumber | The photo's "Serial Number" metadata item in Lightroom's database. |
 +| Exposure | The photo's exposure data, like "1/250 sec at f/5.0". |
 +| ExposureBias | The photo's exposure-bias setting, like "-1 EV". |
 +| ExposureBiasNum | The photo's exposure-bias setting, as a raw number. |
 +| ExposureProgram | The photo's exposure-program setting, like "Aperture priority". |
 +| Flash | One of "no flash", "flash fired", or "unknown flash". |
 +| FocalLength | Focal Length, as a number |
 +| FocalLength35 | Focal Length in 35mm format, as a number |
 +| FocalLength35MM | Focal Length in 35mm format (with locale-specific "mm" appended) |
 +| FocalLengthMM | Focal Length (with locale-specific "mm" appended) |
 +| ISO | The photo's ISO (sensor sensitivity) number. |
 +| Lens | The photo's lens information, like "24-70mm f/2.8". |
 +| MeteringMode | The photo's metering-mode setting, like "Pattern". |
 +| ShutterSpeed | The shutter speed, formatted like "1/60 sec". |
 +| ShutterSpeedNum | The shutter speed as a floating-point number of seconds; Use the "Places" filter to limit precision. |
 +| SubjectDistance | The subject distance as reported by the lens, formatted like "1.2 m". Often wildly inaccurate. |
 +| SubjectDistanceNum | The subject distance as reported by the lens, as a floating-point number. Often wildly inaccurate. |
 +
 +  * TTG Publisher does not support Jeffrey's **CameraName** token.
 +
 +===== Attributes =====
 +
 +| CopyName | The name of the copy (master or virtual) being exported, if any |
 +| Rating | The number of stars assigned to the image: "0" through "5". You can also use with an argument, e.g. ''%%{Rating=*}%%'' or ''%%{Rating=great}%%'' to have, for example, a three-star photo result in %%"***"%% or "great great great". In either case, a photo with a zero rating results in nothing, but you can combine tokens (as described below) along these lines: ''%%{Rating=*|"unrated"}%%''. |
 +| ColorLabel | The "Label" metadata item |
 +| EditCount | A number that goes up each time a change is made in Lightroom to the image or its data. |
 +| UUID | Lightroom's internal unique identifier for the photo, an essentially-random 36-character sequence of letters, numbers, and hyphens, such as "FB4D3F92-455F-47CA-8B7B-7C885F7244FD". |
 +
 +===== Location =====
 +
 +| GPSCoordinates | The photo's geoencoded coordinates, like "35°1'11.51" N 135°46'16.05" E" |
 +| Altitude | The photo's geoencoded altitude, as a number, in meters. Use "Places", e.g. {Altitude:Places=0}, to limit precision. |
 +| GPSAltitude | The photo's geoencoded as a description, e.g. "27.3 m" |
 +| Latitude | Latitude, as a floating-point number. Use "Places", e.g. {Latitude:Places=4}, to limit precision. |
 +| Longitude | Longitude, as a floating-point number. Use "Places", e.g. {Longitude:Places=4}, to limit precision. |
 +| IfGeoencoded | If used in the form {IfGeoencoded=some text here}, the token is replaced by the text after the "=" if the photo is geoencoded, or replaced by nothing if not. If used in the form {IfGeoencoded=some text here;for non-geoencoded} with a semicolon, the text after the semicolon is used when the photo is not geoencoded. |
 +| Location | The "Location" metadata item |
 +| City | The "City" metadata item |
 +| State | The "State" metadata item |
 +| Province | The "State" metadata item |
 +| Country | The "Country" metadata item |
 +| CountryCode | The photo's "Image > ISO Country Code" metadata item in Lightroom's database. |
 +
 +===== Other Metadata =====
 +
 +| Artist | The "Artist" metadata item |
 +| Caption | The "Caption" metadata string |
 +| Category | The photo's "IPTC > Category" metadata item in Lightroom's database. |
 +| Copyright | The "Copyright" metadata item |
 +| CopyrightUrl | The photo's "Copyright Info Url" metadata item in Lightroom's database. |
 +| Creator | The photo's "Contact > Creator" metadata item in Lightroom's database. |
 +| CreatorAddress | The photo's "Contact > Address" metadata item in Lightroom's database. |
 +| CreatorCity | The photo's "Contact > City" metadata item in Lightroom's database. |
 +| CreatorCountry | The photo's "Contact > Country" metadata item in Lightroom's database. |
 +| CreatorEmail | The photo's "Contact > E-Mail" metadata item in Lightroom's database. |
 +| CreatorJobTitle | The photo's "Contact > Job Title" metadata item in Lightroom's database. |
 +| CreatorPhone | The photo's "Contact > Phone" metadata item in Lightroom's database. |
 +| CreatorState | The photo's "Contact > State / Province" metadata item in Lightroom's database. |
 +| CreatorUrl | The photo's "Contact > Website" metadata item in Lightroom's database. |
 +| CreatorZip | The photo's "Contact > Postal Code" metadata item in Lightroom's database. |
 +| DescriptionWriter | The photo's "IPTC > Description Writer" metadata item in Lightroom's database. |
 +| Genre | The photo's "Image > Intellectual Genre" metadata item in Lightroom's database. |
 +| Headline | The "Headline" metadata item |
 +| Instructions | The photo's "Workflow > Instructions" metadata item in Lightroom's database. |
 +| JobIdentifier | The photo's "Workflow > Job Identifier" metadata item in Lightroom's database. |
 +| Keywords | The list of the photo's marked-for-export keywords, separated by commas. (Actually, there's a comma+space pair between each keyword, so it's "plant, rose, flower" and not "plant,rose,flower".) |
 +| IfKeyword | If used in the form {IfKeyword=keyword;some text here}, the token is replaced by the text after the "=" if the photo has been tagged with the named keyword (even if that keyword is not marked in Lightroom as one to be exported). If no text is given after the semicolon, the keyword itself is used: {IfKeyword=public;} becomes "public" or nothing. |
 +| ::: | If used in the form {IfKeyword=keyword;some text here;the not-keyworded text}, with an extra semicolon-separated phrase, the token becomes the not-keyworded if the photo is not tagged with the named keyword. |
 +| IfExportedKeyword | Like IfKeyword, but considers only keywords that have been marked in Lightroom for export. |
 +| OtherCategories | The photo's "IPTC > Other Categories" metadata item in Lightroom's database. |
 +| Provider | The photo's "Workflow > Provider" metadata item in Lightroom's database. |
 +| RightsUsageTerms | The photo's "Workflow > Rights Usage Terms" metadata item in Lightroom's database. |
 +| Scene | The "Scene" metadata item |
 +| Software | The photo's "Software" metadata item in Lightroom's database. |
 +| Source | The "Source" metadata item |
 +| SubjectCode | The photo's "IPTC > IPTC Subject Code" metadata item in Lightroom's database. |
 +| Title | The "Title" metadata item |
 +
 +===== Special =====
 +
 +| PluginProperty=field | Allows you to access the per-image custom metadata kept by a plugin, where field is the plugin's id and the metadata field id, joined with a dot. For example, |
 +| ::: | {PluginProperty=info.regex.lightroom.export.flickr2.url} |
 +| ::: | refers to the url field of the plugin with id info.regex.lightroom.export.flickr2 (Jeffrey's Flickr plugin). However, with PluginProperty, you can reference any plugin data for which you know the plugin id and field name. You can get these from the plugin author, or try digging around the plugin's Info.lua for the plugin id and a reference to its LrMetadataProvider, where you can find field ids. |
 +| Empty | An empty string, perhaps useful for testing. Also, when placed between joining characters, it blocks their squelching. |
 +| " text " | The text as provided. It may not contain the following characters: {   |   }   " |
 +| - | Inserts a hyphen that is never squelched; essentially the same as {"-"} |
 +| , | Inserts a comma that is never squelched; essentially the same as {","} |
 +| LUA | See the section below for details on this advanced, complex token. |
 +
 +===== TTG Publisher Exclusive =====
 +
 +These tokens are original additions to TTG Publisher, and will not cross over to Jeffrey's export plugins.
 +
 +| CellNumber | Outputs the sequential number of the image in the gallery. The first image is 1, the second image is 2, etc. |
 +
 +===== Token Basics =====
 +
 +As mentioned above, tokens are identified within a template by wrapping them with ''%%{ ... }%%''. The value generated by the token has leading and trailing spaces removed before being inserted into the result. For example, if the "Caption" metadata item is the string "My Vacation  ", the value actually used for the Caption token (which appears as ''%%{Caption}%%'' in the template) is "My Vacation".
 +
 +===== Combining Tokens =====
 +
 +You may list multiple tokens within { ... }, separated by | (a vertical bar). In such a case, the first token that results in non-empty text is used. Tokens may result in an empty value if the photo is missing the associated metadata. For example, if a photo is missing the "date taken" metadata, the YYYY token is empty. Thus, the previous copyright example may be better written as:
 +
 +''%%Copyright {YYYY|yyyy} {Artist}%%''
 +
 +In this case, if the ''%%YYYY%%'' token is empty, the ''%%yyyy%%'' token (the current year, which can never be empty) is used.
 +
 +Continuing with this example, because the Artist token results in an empty item if there is no artist metadata, this example might be written as:
 +
 +''%%Copyright {YYYY|yyyy} {Artist|"by the photographer"}%%''
 +
 +... to become:
 +
 +Copyright 2008 by the photographer
 +
 +... when there is no artist metadata.
 +
 +===== Token Filters =====
 +
 +Filters allow you to modify the text that a token generates. For example, applying the S2U filter ("Space to Underscore") to the "Caption" example given earlier results in a value of "My_Vacation". To indicate that a filter should be applied to a token, append it to the token name with a colon. This example appears would appear in a template as ''%%{Caption:S2U}%%''.
 +
 +Token filters:
 +
 +| S2U | Space to Underscore | Any sequences of spaces (and/or underscores) are replaced by a single underscore |
 +| S2D | Space to Dash | Any sequences of spaces (and/or dashes) are replaced by a single dash |
 +| U2S | Underscore to Space | Any sequences of underscores (and/or spaces) are replaced by a single space |
 +| D2S | Dash to Space | Any sequences of dashes (and/or spaces) are replaced by a single space |
 +| DU2S | Dash/Underscore to Space | Any sequences of dashes, underscores, and/or spaces are replaced by a single space |
 +| Places=num | specify numeric precision | If the item is number, formats it to num decimal places. If the item is not a number, makes it empty. |
 +| After=text | Use value to the right of text | If the given text is found in the value that the token generates, strip it and all that appeared before (to the left), leaving only what appears to the right of text in the value. If the text is not found in the value, the result of the token is empty. |
 +| ::: | ::: | For example, if you tend to use captions like "My trip to Paris" and "My trip to the Canadian Rockies", and you wanted shorter text, you might consider using {Caption:After=trip to} to result in values like "Paris" and "the Canadian Rockies". |
 +| ::: | ::: | If you wanted to implement an idea such as "Strip the '...trip to' text from the caption if it's there, and use the unadulterated caption if not", you would append an unadorned Caption token as described in the "Combining Tokens" section above, resulting in {Caption:After=trip to%%|%%Caption}. |
 +| UC | Upper Case | Capitalizes the item |
 +| LC | Lower Case | Ensures the item is all lower case. |
 +
 +
 +  * TTG Publisher does not support Jeffrey's **Length=num**, **UCWords**, **UCFirst** and **LCFirst** filters.
 +
 +
 +/*
 +| Length=num | specify max length | If the item is longer than num characters long, it is truncated to the first num characters. Treats the text as UTF-8. |
 +| UCFirst | Upper Case (first character) | Capitalizes the first character of the item. |
 +| UCWords | Upper Case Words | Capitalizes the first character of the item, and any character after a space or hyphen. |
 +| LCFirst | Lower Case (first character) | Lowers the case of the first character of the item. |
 +*/
 +
 +
 +
 +===== Squelching Superfluous Joining Characters =====
 +
 +  * TTG Publisher does not support squelching superfluous joining characters.
 +
 +/* Within a template, joining characters are special:
 +
 +space \\ 
 +comma \\ 
 +hyphen/minus \\ 
 +colon \\ 
 +the <br> and <br/> sequences
 +
 +After a photo-specific value has been computed from a template, all leading and trailing joining characters are removed, and embedded repetitions are replaced by a single item.
 +
 +As an example of the first case, consider
 +
 +''%%Copyright {YYYY|yyyy} {Artist}%%''
 +
 +... when there is no artist metadata. Without these special rules, this would result in the derived value having trailing space, but the special squelching rules remove it.
 +
 +As another example, consider the template:
 +
 +''%%{Location}-{Country}-{State}-{City}-{Caption}%%''
 +
 +... for a photo that has "Location" and "Caption", but no "Country," "City," or "State.". Assuming that location and caption are "Home" and "Having Fun" respectively, it becomes:
 +
 +Home-Having Fun
 +
 +... which is better than it would be without these special rules:
 +
 +Home----Having Fun
 +
 +Note that space, comma, and hyphen/minus are only special when they're part of the template itself. When they are part of the value derived from a token (such as the space in "Having Fun" above), they are never considered for squelching.
 +
 +As such, you can use either ''%%{-}%%'' or ''%%{"-"}%%'' to include a hyphen/minus that will never be squelched. Similarly, you can use ''%%{,}%%'' or ''%%{","}%%'' for a comma.
 +*/
 +
 +==== The special {Empty} token ====
 +
 +The ''%%{Empty}%%'' token produces no text, but has the side effect in that it interrupts the squelching of joining characters. Without it, the sequence "<br><br>" becomes "<br>" but with it, "<br>{EMPTY}<br>" becomes "<br><br>".
 +
 +==== The special {NOJOINERS} token ====
 +
 +
 +  * TTG Publisher does not support the {NOJOINERS} token.
 +
 +/*
 +As mentioned above, leading and trailing joining characters are stripped, but sometimes you want them stripped whenever they appear in a certain context. For example, the template:
 +
 +''%%<span class='where'>{City}, {State}</span>%%''
 +
 +... results in something like "<span class='where'>Paris, </span>" if City is "Paris" but State has no value. In this case you'd like to mark the start and end of the <span> as being places where no joining characters should accumulate, just as they shouldn't accumulate at the start and end of the whole specification.
 +
 +To do this, put the special ''%%{NOJOINERS}%%'' token in these spots, e.g.
 +
 +''%%<span class='where'>{NOJOINERS}{City}, {State}{NOJOINERS}</span>%%''
 +
 +The exact rules for how joining characters are squelched are complex, but they are designed to produce a common-sense result.
 +*/
 +
 +==== The Special {LUA=...} Token ====
 +
 +This advanced programming-like feature allows you to execute arbitrary Lua code, in an environment where the tokens above have been prepopulated into variables. For example:
 +
 +''%%{LUA=CreatorPhone}%%''
 +
 +... and ...
 +
 +''%%{LUA=return CreatorPhone}%%''
 +
 +... are exactly the same as the {CreatorPhone} token, but, for example:
 +
 +''%%{LUA=  if  CreatorPhone ~= ''  then    return sprintf("Contact: %s", CreatorPhone)  end  }%%''
 +
 +... becomes the string "Contact: text-from-CreatorPhone" if the CreatorPhone token is not empty, nothing if it is.
 +
 +The special Lua environment, in the latest version of plugins running in the latest version of Lightroom, includes:
 +
 +  * Variables exist for almost all of the tokens (except //DaysSince//, //IfGeoencoded//, etc. — tokens that require an extra argument). Each one is a string; if the token has no value, its variable in the special Lua environment is the empty string ''.
 +  * The standard Lua functions **tonumber()**, **tostring()**, **type()**, **unpack()**, **ipairs()**, and **pairs()**.
 +  * The standard Lua name spaces **string**, **table**, and **math**. The **os** namespace is partially included: **os.date()**, **os.time()**, and **os.tmpname()**.
 +  * The Lightroom SDK namespaces **LrDate**, **LrPathUtils**, and **LrStringUtils**. SDK docs can be downloaded [[http://www.adobe.com/devnet/photoshoplightroom.html|here]].
 +  * The Booleans **WIN** and **MAC**, which indicate the type of host operating system, and **sprintf()**, which is a synonym for **string.format()**.
 +  * The function **TBL(...)**, which returns a new table, populating it with any arguments provided. This is to help avoid curly braces in inlined Lua.
 +  * The function **ne(item)**, meaning "non-empty". It returns **nil** if the item is **nil** or **tostring(item)** evaluates to a zero-length string.
 +  * The function **nb(item)**, meaning "non-blank". It returns **nil** if the item is **nil** or **tostring(item)** evaluates to a string that has no non-whitespace characters.
 +  * The variable **photoTime**, which returns the Cocoa timestamp of the photo in question, if any. This is suitable for passing to Lightroom's **LrDate.timestampToComponents()** and **LrDate.timeToUserFormat()** functions, among others. Add 978307200 to get a Unix Time.
 +  * The variable **currentTime**, which returns the current Cocoa timestamp; identical to **LrDate.currentTime()**.
 +  * A table **KW** that has keys for every keyword applied to the photo (the values are true), and a similar table **KWE** with keys for exported keywords. Thus, the code snippet **KW.private** is true if the keyword "private" has been applied to the photo, **nil** otherwise.
 +  * The function **load()**, which executes Lua code in a named file, as discussed below.
 +
 +Here are some examples. Some have been broken into multiple lines for display, with pretty indenting, for easier reading one this page; when inputting into the plugin, you'll have to put it all on one big long (ugly) line ...
 +
 +<code>
 +{LUA=if Artist ~= "" then return sprintf("Copyright %s", Artist) end} 
 +</code>
 +
 +Becomes "Copyright ..." with the name of the Artist if there is an Artist token.
 +
 +----
 +
 +<code>
 +{LUA=if Artist ~= "" and Copyright = "" then return sprintf("Copyright %s", Artist) end} 
 +</code>
 +
 +Like the one above, but only if there is no Copyright token.
 +
 +----
 +
 +<code>
 +{LUA=if Artist ~= "" then return sprintf("Copyright %s %s", yyyy, Artist) end} 
 +</code>
 +
 +Becomes "Copyright %%####%% ...." with the current year and the name of the Artist, if there is an Artist token.
 +
 +----
 +
 +<code>
 +{LUA=if Artist ~= "" then
 +   if yyyy == YYYY or YYYY == "" then
 +      return sprintf("Copyright %s %s", yyyy, Artist)
 +   else
 +      return sprintf("Copyright %s-%s %s", YYYY, yyyy, Artist)
 +   end
 +end}
 +</code>
 +
 +Like the one above, but the reference to the year in the copyright statement becomes a range if the photo has a date associated with it and that date is not the current year, e.g. "Copyright 2006-2010 Jeffrey Friedl" for a photo taken in 2006 and being processed in 2010.
 +
 +----
 +
 +<code>
 +{LUA=if Artist ~= "" then
 +   when = YYYY==yyyy or YYYY=="" and yyyy or YYYY.."-"..yyyy
 +   return sprintf("Copyright %s %s", when, Artist)
 +end} 
 +</code>
 +Exactly like the one just above.
 +
 +----
 +
 +<code>
 +{LUA=if GPSCoordinates ~= "" then return sprintf("geo:lat=%s;geo:lon=%s", Latitude, Longitude) end} 
 +</code>
 +
 +If the photo is geoencoded, becomes GPS machine tags.
 +
 +----
 +
 +<code>
 +{LUA=if KW.private and not KWE.private then return "private, but not reporting as such" end} 
 +</code>
 +
 +Becomes "private, but not reporting as such" if marked with the keyword "private", but that keyword is not marked for export.
 +
 +----
 +
 +===== Loading From a File =====
 +
 +
 +  * TTG Publisher does not support Loading Lua from a file.
 +
 +/*
 +In Lightroom 3 and later, the **load()** function loads Lua code from a file. You can load a library of routines and then make reference to the routines later in the %%{LUA= ... }%%, or you can simply return the value of **load()**, which is the value returned at the end of the file:
 +
 +<code>
 +{LUA= return load("/full/path/to/your/lua/file.lua") }
 +</code>
 +
 +This allows you to keep the tokens that appear in little plugin fields more manageable, yet lets you easily access arbitrarily-complex logic.
 +*/
Print/export