Skip to content

Instantly share code, notes, and snippets.

@vorbei
Last active June 15, 2022 02:05
Show Gist options
  • Save vorbei/b4d4ed714c80cbaab3546970af67b240 to your computer and use it in GitHub Desktop.
Save vorbei/b4d4ed714c80cbaab3546970af67b240 to your computer and use it in GitHub Desktop.
Sketch 中英文复合字体插件
const fontManager = [NSFontManager sharedFontManager];
const UI = require('sketch/ui');
//注意:更新后的插件版本,配置请填写 Font Family 名称,请不要再选择 Postscript 名称
//顺序:英文字体,中文字体,数字字体(请依照自己安装的字体和喜好配置)
const options = {
'SF, 苹方, Mono':
'SF Pro Text, PingFang SC, SF Mono',
'Arial, 微软雅黑':
'Arial, Microsoft YaHei',
'New York, 思源宋体':
'New York Medium,Source Han Serif CN',
'Space Grotesk, 思源黑体, Mono Regular':
'Space Grotesk, Source Han Sans CN, SF Mono',
'Inter, 思源黑体':
'Inter,Source Han Sans CN'
}
const latin_re = /[\u0020-\u00FF]+/mg;
const digit_re = /[0-9\.,\-]+/mg;
const cjk_re = /[\u2000-\uFFE0]+/mg;
const sfsymbol_re = /[\u{100000}-\u{1006EA}]+/ug;
let stats = {layers: 0, latin_ranges:0, cjk_ranges: 0, digit_ranges: 0}
function reHelper (re, text){
let buffer, ranges = [];
while ((buffer = re.exec(text)) !== null) {
res = { "string": buffer[0], "start": buffer.index, "length": buffer[0].length};
ranges.push(NSMakeRange(res.start,res.length))
}
return ranges;
}
function fontHelper (fn,size) { return NSFont.fontWithName_size(fn,size?size:16) };
function changeFont(newFamily, oldFont){
const font = [fontManager fontWithFamily:newFamily traits:oldFont.traits weight:oldFont.weight size:oldFont.size];
return font;
}
function fontInRange (layer,range){
const sub = [[layer attributedStringValue] attributedSubstringFromRange: range];
const _range = sub.treeAsDictionary().attributes[0].NSFont
const fontFamily = _range.family;
const fontPostScriptName = _range.attributes.NSFontNameAttribute;
const fontSize = _range.attributes.NSFontSizeAttribute;
const _font = fontHelper(fontPostScriptName,fontSize);
const fontWeight = [fontManager weightOfFont:_font];
const fontTraits = [fontManager traitsOfFont:_font];
const font = {
family: fontFamily,
weight: fontWeight,
traits: fontTraits,
size: fontSize,
name: fontPostScriptName
}
return font;
}
function updateLayers(latin_font, cjk_font, digit_font){
let selectedLayers = context.selection;
let layers = selectedLayers;
let sf_font = "SF Pro Text";
stats.layers += layers.length;
layers.forEach(function(layer){
if (layer.className() != 'MSTextLayer') return;
let text = layer.stringValue();
let latin_ranges = latin_font?reHelper(latin_re,text):[];
let cjk_ranges = cjk_font?reHelper(cjk_re, text):[];
let digit_ranges = digit_font?reHelper(digit_re,text):[];
let sfsymbol_ranges = digit_font?reHelper(sfsymbol_re,text):[];
stats.latin_ranges += latin_ranges.length;
stats.cjk_ranges += cjk_ranges.length;
stats.digit_ranges += digit_ranges.length;
layer.setIsEditingText(true);
cjk_ranges.forEach(function(range){
layer.addAttribute_value_forRange(NSFontAttributeName, changeFont(cjk_font, fontInRange(layer,range)), range);
});
latin_ranges.forEach(function(range){
layer.addAttribute_value_forRange(NSFontAttributeName, changeFont(latin_font, fontInRange(layer,range)), range);
});
digit_ranges.forEach(function(range){
layer.addAttribute_value_forRange(NSFontAttributeName, changeFont(digit_font, fontInRange(layer,range)), range);
});
sfsymbol_ranges.forEach(function(range){
layer.addAttribute_value_forRange(NSFontAttributeName, changeFont(sf_font, fontInRange(layer,range)), range);
});
layer.setIsEditingText(false);
})
};
UI.getInputFromUser("请选择英文、中文、数字字体(可选)", {
type: UI.INPUT_TYPE.selection,
possibleValues: Object.keys(options)
}, (err, value) => {
if (err) {
return;
} else {
let fonts = options[value].split(/ *, */);
updateLayers(fonts[0],fonts[1],fonts[2]);
statsMsg = `共设置 ${stats.layers} 个图层:英文 ${stats.latin_ranges} 段, 中文 ${stats.cjk_ranges} 段,数字 ${stats.digit_ranges} 段。`;
log(statsMsg);
UI.message(statsMsg);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment