Skip to content

Commit

Permalink
feat: Add support for CSS shorthand property 'all'
Browse files Browse the repository at this point in the history
  • Loading branch information
MurakamiShinyu committed Jul 14, 2022
1 parent a5b77fd commit 1f809cd
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 36 deletions.
1 change: 1 addition & 0 deletions packages/core/src/vivliostyle/assets.ts
Expand Up @@ -686,6 +686,7 @@ border-inline-end-width: 3px;
SHORTHANDS
all = ALL;
background = COMMA background-image [background-position [ / background-size ]] background-repeat
background-attachment [background-origin background-clip] background-color; /* background-color is a special case, see the code */
border-top = border-top-width border-top-style border-top-color;
Expand Down
6 changes: 4 additions & 2 deletions packages/core/src/vivliostyle/css-cascade.ts
Expand Up @@ -121,7 +121,7 @@ export const inheritedProps = {

export const polyfilledInheritedProps = [
"box-decoration-break",
// TODO: box-decoration-block should not be inherited.
// TODO: box-decoration-break should not be inherited.
// https://github.com/vivliostyle/vivliostyle.js/issues/259
"image-resolution",
"orphans",
Expand Down Expand Up @@ -3323,7 +3323,9 @@ export class CascadeParserHandler
if (!name && !ns) {
return;
}
this.specificity += 1;
if (name) {
this.specificity += 1;
}
if (name && ns) {
this.chain.push(new CheckNSTagAction(ns, name.toLowerCase()));
} else if (name) {
Expand Down
44 changes: 28 additions & 16 deletions packages/core/src/vivliostyle/css-page.ts
Expand Up @@ -246,36 +246,48 @@ export function resolvePageSizeAndBleed(style: {
}
}
}
const marks = style["marks"];
const bleed = style["bleed"];
if (!bleed || bleed.value === Css.ident.auto) {
const marksCV = style["marks"];
const bleedCV = style["bleed"];
const marks =
marksCV && !Css.isDefaultingValue(marksCV.value)
? marksCV.value
: Css.ident.none;
const bleed =
bleedCV && !Css.isDefaultingValue(bleedCV.value)
? bleedCV.value
: Css.ident.auto;
if (bleed === Css.ident.auto) {
// "('auto' value) Computes to 6pt if marks has crop and to zero
// otherwise." https://drafts.csswg.org/css-page/#valdef-page-bleed-auto
if (marks) {
if (marks !== Css.ident.none) {
let hasCrop = false;
if (marks.value.isSpaceList()) {
hasCrop = (marks.value as Css.SpaceList).values.some(
if (marks.isSpaceList()) {
hasCrop = (marks as Css.SpaceList).values.some(
(v) => v === Css.ident.crop,
);
} else {
hasCrop = marks.value === Css.ident.crop;
hasCrop = marks === Css.ident.crop;
}
if (hasCrop) {
pageSizeAndBleed.bleed = new Css.Numeric(6, "pt");
}
}
} else if (bleed.value && bleed.value.isNumeric()) {
pageSizeAndBleed.bleed = bleed.value as Css.Numeric;
} else if (bleed.isNumeric()) {
pageSizeAndBleed.bleed = bleed as Css.Numeric;
}

// crop-offset (Issue #913)
const cropOffset = style["crop-offset"];
if (!cropOffset || cropOffset.value === Css.ident.auto) {
if (marks && marks.value !== Css.ident.none) {
const cropOffsetCV = style["crop-offset"];
const cropOffset =
cropOffsetCV && !Css.isDefaultingValue(cropOffsetCV.value)
? cropOffsetCV.value
: Css.ident.auto;
if (cropOffset === Css.ident.auto) {
if (marks !== Css.ident.none) {
pageSizeAndBleed.bleedOffset = defaultBleedOffset;
}
} else if (cropOffset.value && cropOffset.value.isNumeric()) {
pageSizeAndBleed.cropOffset = cropOffset.value as Css.Numeric;
} else if (cropOffset.isNumeric()) {
pageSizeAndBleed.cropOffset = cropOffset as Css.Numeric;
}
return pageSizeAndBleed;
}
Expand Down Expand Up @@ -2496,8 +2508,8 @@ export class PageManager {
pseudoName: pageRuleMasterPseudoName,
});
const pageMasterStyle = newPageMaster.specified;
const size = style["size"];
if (size) {
const size: CssCascade.CascadeValue = style["size"];
if (size && !Css.isDefaultingValue(size.value)) {
const pageSize = resolvePageSizeAndBleed(style as any);
const priority = size.priority;
pageMasterStyle["width"] = CssCascade.cascadeValues(
Expand Down
11 changes: 7 additions & 4 deletions packages/core/src/vivliostyle/css-styler.ts
Expand Up @@ -231,7 +231,7 @@ export class Box {

styleValue(name: string, defaultValue?: Css.Val): Css.Val | null {
if (!(name in this.styleValues)) {
const cv = this.style[name];
const cv: CssCascade.CascadeValue = this.style[name];
this.styleValues[name] = cv
? cv.evaluate(this.context, name)
: defaultValue || null;
Expand Down Expand Up @@ -374,8 +374,7 @@ export class BoxStack {
.styleValue("white-space", Css.ident.normal)
.toString();
const whitespace = Vtree.whitespaceFromPropertyValue(whitespaceValue);
Asserts.assert(whitespace !== null);
if (!Vtree.canIgnore(node, whitespace)) {
if (whitespace && !Vtree.canIgnore(node, whitespace)) {
this.atBlockStart = false;
this.atFlowStart = false;
}
Expand Down Expand Up @@ -987,7 +986,11 @@ export class Styler implements AbstractStyler {

if (blockStartOffset === 0) {
// Named page type at first page
const pageType = style["page"]?.value.toString();
const pageCV: CssCascade.CascadeValue = style["page"];
const pageType =
pageCV &&
!Css.isDefaultingValue(pageCV.value) &&
pageCV.value.toString();
if (pageType && pageType.toLowerCase() !== "auto") {
this.cascade.firstPageType = pageType;
}
Expand Down
99 changes: 99 additions & 0 deletions packages/core/src/vivliostyle/css-validator.ts
Expand Up @@ -1483,6 +1483,104 @@ export class FontShorthandValidator extends SimpleShorthandValidator {
}
}

const propsExcludedFromAll = [
"unicode-bidi",
"direction",

// excludes css-logical
"margin-block-start",
"margin-block-end",
"margin-inline-start",
"margin-inline-end",
"padding-block-start",
"padding-block-end",
"padding-inline-start",
"padding-inline-end",
"border-block-start-color",
"border-block-end-color",
"border-inline-start-color",
"border-inline-end-color",
"border-block-start-style",
"border-block-end-style",
"border-inline-start-style",
"border-inline-end-style",
"border-block-start-width",
"border-block-end-width",
"border-inline-start-width",
"border-inline-end-width",
"block-start",
"block-end",
"inline-start",
"inline-end",
"block-size",
"inline-size",
"max-block-size",
"max-inline-size",
"min-block-size",
"min-inline-size",

// excludes non-standards and special
"behavior",
"bleed",
"conflicting-partitions",
"crop-offset",
"enabled",
"flow-consume",
"flow-from",
"flow-into",
"flow-linger",
"flow-options",
"flow-priority",
"font-display",
"font-size-adjust",
"font-stretch_css3",
"font-variant_css2",
"glyph-orientation-vertical",
"marks",
"min-page-height",
"min-page-width",
"repeat-on-break",
"required",
"required-partitions",
"ruby-align",
"shape-inside",
"snap-height",
"snap-width",
"template",
"text-decoration-skip",
"text-justify",
"text-zoom",
"unicode-range",
"utilization",
"wrap-flow",
];

export class AllShorthandValidator extends SimpleShorthandValidator {
constructor() {
super();
}

/**
* @override
*/
init(syntax: ShorthandSyntaxNode[], propList: string[]): void {
super.init(syntax, propList);
for (const name in this.validatorSet.validators) {
if (!propsExcludedFromAll.includes(name)) {
this.propList.push(name);
}
}
}

/**
* @override
*/
validateList(list: Css.Val[]): number {
this.error = true;
return 0;
}
}

export const shorthandValidators: {
[key: string]: typeof ShorthandValidator;
} = {
Expand All @@ -1491,6 +1589,7 @@ export const shorthandValidators: {
INSETS_SLASH: InsetsSlashShorthandValidator,
COMMA: CommaShorthandValidator,
FONT: FontShorthandValidator,
ALL: AllShorthandValidator,
};

//---- validation grammar parser and public property validator
Expand Down
5 changes: 4 additions & 1 deletion packages/core/src/vivliostyle/display.ts
Expand Up @@ -84,7 +84,10 @@ export function getComputedDislayValue(
} else if (isAbsolutelyPositioned(position)) {
float = Css.ident.none;
display = blockify(display);
} else if ((float && float !== Css.ident.none) || isRoot) {
} else if (
(float && float !== Css.ident.none && !Css.isDefaultingValue(float)) ||
isRoot
) {
display = blockify(display);
}
return { display, position, float };
Expand Down
14 changes: 7 additions & 7 deletions packages/core/src/vivliostyle/page-master.ts
Expand Up @@ -320,7 +320,7 @@ export function toExprIdent(
val: Css.Val,
def: string,
): Exprs.Val {
if (!val) {
if (!val || Css.isDefaultingValue(val)) {
return new Exprs.Const(scope, def);
}
return val.toExpr(scope, scope.zero);
Expand All @@ -331,7 +331,7 @@ export function toExprAuto(
val: Css.Val,
ref: Exprs.Val,
): Exprs.Val {
if (!val || val === Css.ident.auto) {
if (!val || val === Css.ident.auto || Css.isDefaultingValue(val)) {
return null;
}
return val.toExpr(scope, ref);
Expand All @@ -342,7 +342,7 @@ export function toExprNormal(
val: Css.Val,
ref: Exprs.Val,
): Exprs.Val {
if (!val || val === Css.ident.normal) {
if (!val || val === Css.ident.normal || Css.isDefaultingValue(val)) {
return null;
}
return val.toExpr(scope, ref);
Expand All @@ -353,7 +353,7 @@ export function toExprZero(
val: Css.Val,
ref: Exprs.Val,
): Exprs.Val {
if (!val || val === Css.ident.auto) {
if (!val || val === Css.ident.auto || Css.isDefaultingValue(val)) {
return scope.zero;
}
return val.toExpr(scope, ref);
Expand All @@ -369,7 +369,7 @@ export function toExprZeroAuto(
val: Css.Val,
ref: Exprs.Val,
): Exprs.Val {
if (!val) {
if (!val || Css.isDefaultingValue(val)) {
return scope.zero;
} else if (val === Css.ident.auto) {
return null;
Expand All @@ -384,7 +384,7 @@ export function toExprZeroBorder(
styleVal: Css.Val,
ref: Exprs.Val,
): Exprs.Val {
if (!val || styleVal === Css.ident.none) {
if (!val || styleVal === Css.ident.none || Css.isDefaultingValue(val)) {
return scope.zero;
}
return val.toExpr(scope, ref);
Expand All @@ -395,7 +395,7 @@ export function toExprBool(
val: Css.Val,
def: Exprs.Val,
): Exprs.Val {
if (!val) {
if (!val || Css.isDefaultingValue(val)) {
return def;
}
if (val === Css.ident._true) {
Expand Down
18 changes: 12 additions & 6 deletions packages/core/src/vivliostyle/vgen.ts
Expand Up @@ -679,11 +679,12 @@ export class ViewFactory
elementStyle = inheritedValues.elementStyle;
this.nodeContext.lang = inheritedValues.lang;
}
const floatReferenceCV: CssCascade.CascadeValue =
elementStyle["float-reference"];
const floatReference =
elementStyle["float-reference"] &&
PageFloats.floatReferenceOf(
elementStyle["float-reference"].value.toString(),
);
floatReferenceCV &&
!Css.isDefaultingValue(floatReferenceCV.value) &&
PageFloats.floatReferenceOf(floatReferenceCV.value.toString());
if (
this.nodeContext.parent &&
floatReference &&
Expand Down Expand Up @@ -846,8 +847,11 @@ export class ViewFactory
this.nodeContext.floatSide = floating ? floatSide.toString() : null;
this.nodeContext.floatReference =
floatReference || PageFloats.FloatReference.INLINE;
const floatMinWrapBlock = computedStyle["float-min-wrap-block"];
this.nodeContext.floatMinWrapBlock =
computedStyle["float-min-wrap-block"] || null;
floatMinWrapBlock && !Css.isDefaultingValue(floatMinWrapBlock)
? floatMinWrapBlock
: null;
this.nodeContext.columnSpan = computedStyle["column-span"];
if (!this.nodeContext.inline) {
const breakAfter = computedStyle["break-after"];
Expand All @@ -859,7 +863,9 @@ export class ViewFactory
this.nodeContext.breakBefore = breakBefore.toString();
}
// Named page type
let pageType = computedStyle["page"]?.toString() || null;
const pageVal: Css.Val = computedStyle["page"];
let pageType =
pageVal && !Css.isDefaultingValue(pageVal) && pageVal.toString();
if (!pageType || pageType.toLowerCase() === "auto") {
pageType = this.nodeContext.pageType;
} else {
Expand Down

0 comments on commit 1f809cd

Please sign in to comment.