File size: 8,762 Bytes
e4a10af |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const iconv_corefoundation_1 = require("iconv-corefoundation");
const smart_buffer_1 = require("smart-buffer");
const Context_1 = require("./Context");
const util_1 = require("./util");
const errors_1 = require("./util/errors");
const format_verror_1 = require("./util/format-verror");
const PromiseEach_1 = require("./util/PromiseEach");
const { freeze } = Object;
class NoDefaultLabelsError extends Error {
constructor(lang, message) {
super(message || `There are no default labels for ${lang.englishName}. You must provide your own labels for this language.`);
this.lang = lang;
}
}
exports.NoDefaultLabelsError = NoDefaultLabelsError;
NoDefaultLabelsError.prototype.name = NoDefaultLabelsError.name;
class LabelEncodingError extends format_verror_1.PrettyVError {
constructor(labelDescription, lang, cause, ...params) {
super({ cause: typeof cause === "string" ? undefined : cause }, `Cannot encode %s for %s${typeof cause === "string" ? "%s" : cause ? "" : "."}`, labelDescription, lang.englishName, typeof cause === "string" ? cause : undefined, ...params);
}
}
exports.LabelEncodingError = LabelEncodingError;
LabelEncodingError.prototype.name = LabelEncodingError.name;
var Labels;
(function (Labels) {
Labels.names = freeze(["languageName", "agree", "disagree", "print", "save", "message"]);
Labels.descriptions = freeze({
agree: "“Agree” button label",
disagree: "“Disagree” button label",
languageName: "Language name",
message: "License agreement instructions text",
print: "“Print” button label",
save: "“Save” button label"
});
async function fromPromises(labels) {
const labelPromises = [];
const result = {};
for (const key of Labels.names) {
const p = labels[key];
if (p) {
labelPromises.push(p.then(label => {
result[key] = label;
}));
}
}
await PromiseEach_1.default(labelPromises);
return result;
}
Labels.fromPromises = fromPromises;
function mapAsync(labels, fun, options) {
return fromPromises(map(labels, fun, options));
}
Labels.mapAsync = mapAsync;
function map(labels, fun, { onNoLanguageName } = {}) {
const result = {};
Labels.forEach(labels, (label, key) => {
result[key] = fun(label, key, labels);
}, {
onNoLanguageName: onNoLanguageName ? () => {
result.languageName = onNoLanguageName();
} : undefined
});
return result;
}
Labels.map = map;
function forEach(labels, fun, { onNoLanguageName } = {}) {
for (const name of Labels.names) {
const label = labels[name];
if (label === undefined && name === "languageName") {
if (onNoLanguageName)
onNoLanguageName();
}
else
fun(label, name, labels);
}
}
Labels.forEach = forEach;
function create(fun, { includeLanguageName = false } = {}) {
const labels = {};
Labels.names.forEach((key, index) => {
if (includeLanguageName || key !== "languageName")
labels[key] = fun(key, index);
});
return labels;
}
Labels.create = create;
function createAsync(fun, options) {
return fromPromises(create(fun, options));
}
Labels.createAsync = createAsync;
/**
* Prepares a label set for insertion into a disk image as a `STR#` resource.
*
* @remarks
* Throws {@link LabelEncodingError} if there is a problem encoding some of the labels.
*
* Throws {@link verror#MultiError} if there is more than one error.
*
* @param labels - The label set to prepare.
*
* @param lang - The language to prepare the label set for. This determines the target character set.
*
* @returns A `Buffer` in `STR#` format.
*/
function prepare(labels, lang) {
const sbuf = new smart_buffer_1.SmartBuffer();
function writeStr(string, description, isDefaultLanguageName = false) {
let data;
try {
data = lang.charset.encode(string);
}
catch (e) {
errors.add(isDefaultLanguageName && e instanceof iconv_corefoundation_1.NotRepresentableError ?
new NoDefaultLabelsError(lang, `The default languageName label for ${lang.englishName}, “${lang.localizedName}”, is not representable in ${lang.charset}, the native character set for that language. Please provide a languageName label for this language that is representable in that character set.`) :
new LabelEncodingError(description, lang, e));
return;
}
const length = data.length;
if (length > 255) {
const e = new LabelEncodingError(description, lang, "the label is too large to write into a STR# resource. The maximum size is 255 bytes, but it is %d bytes.", length);
e.text = data;
errors.add(e);
return;
}
if (errors.isEmpty) {
sbuf.writeUInt8(length);
sbuf.writeBuffer(data);
}
}
// Magic
sbuf.writeUInt16BE(6);
// Labels
const errors = new errors_1.ErrorBuffer();
Labels.forEach(labels, (label, key) => writeStr(label, Labels.descriptions[key]), { onNoLanguageName() {
// If no language name is provided, try the languageName in the built-in labels, or failing that, the language's localizedName.
writeStr(lang.labels && lang.labels.languageName || lang.localizedName, Labels.descriptions.languageName, true);
} });
errors.check();
return sbuf.toBuffer();
}
Labels.prepare = prepare;
/**
* Prepares the given language's default label set for insertion into a disk image as a `STR#` resource.
*
* @remarks
* Throws {@link NoDefaultLabelsError} if there is no default label set for the given language.
*
* Throws {@link LabelEncodingError} if there is a problem encoding some of the labels.
*
* Throws a {@link verror#MultiError} if there is more than one error.
*
* @param lang - The language to prepare the label set for.
*
* @param contextOrOptions - Context of an existing {@link dmgLicense} run, or options for one (when calling this function standalone).
*
* @returns A `Buffer` in `STR#` format.
*/
function prepareDefault(lang) {
const labels = lang.labels;
if (!labels)
throw new NoDefaultLabelsError(lang);
return Labels.prepare(labels, lang);
}
Labels.prepareDefault = prepareDefault;
/**
* Prepares a label set for insertion into a disk image as a `STR#` resource.
*
* @remarks
* This function delegates to `prepareDefault` or `prepare` as appropriate.
*
* Throws {@link NoDefaultLabelsError} if `labels` is `null` or `undefined` and there is no default label set for the given language.
*
* Throws {@link LabelEncodingError} if there is a problem encoding some of the labels.
*
* Throws a {@link verror#MultiError} if there is more than one error.
*
* @param labels - An object describing the label set to prepare. If `null` or `undefined`, the default label set for the given language is used instead.
*
* @param lang - The language to prepare the label set for. This determines the target character set, and if `labels` is `null` or `undefined`, which language's default label set to use.
*
* @param contextOrOptions - Context of an existing {@link dmgLicense} run, or options for one (when calling this function standalone). Used to resolve relative paths if `labels` is a `LabelsSpec.LabelsRaw`.
*
* @returns A `Buffer` in `STR#` format.
*/
async function prepareSpec(labels, lang, contextOrOptions) {
if (!labels)
return prepareDefault(lang);
else if (labels.file) {
const context = Context_1.default.from(contextOrOptions);
return util_1.readFileP(context.resolvePath(labels.file));
}
else
return prepare(labels, lang);
}
Labels.prepareSpec = prepareSpec;
})(Labels = exports.Labels || (exports.Labels = {}));
Object.defineProperty(Labels, Symbol.toStringTag, { value: "Labels" });
exports.default = Labels;
//# sourceMappingURL=Labels.js.map |