-
Notifications
You must be signed in to change notification settings - Fork 3.9k
/
validator.proto
1076 lines (970 loc) · 45.6 KB
/
validator.proto
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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
syntax = "proto2";
// TODO(b/188065554) Deprecate automatic generation of validator.pb.go.
option go_package = "./validator.proto;amp_validator";
// Package defines Validator protobuffers. This is a package comment required by
// Golint for validator.pb.go, but Golint still fails with an error "Package
// amp_validator (defined in [validator.pb.go]) should have a package comment".
// This happens because protoc adds an extra line after the comment. Ignore the
// error.
package amp.validator;
// Used for validating attributes that require another attribute for some
// given set of conditions.
// E.g. attr name: "on" if_value_regex: "tap:.*" also_require_attr: "role"
// NEXT AVAILABLE TAG: 3
message AttrTriggerSpec {
// If set, attribute's value must match to also require attribute(s).
// If not set, attribute automatically also require attribute(s).
optional string if_value_regex = 1; // case sensitive
// If set, other attributes - identified by their name string - must
// be present as well.
repeated string also_requires_attr = 2;
}
// Used for validating properties in attribute values. Our validator
// (via parse-viewport.h) implements the parsing algorithm as described here:
// https://drafts.csswg.org/css-device-adapt/#parsing-algorithm
// NEXT AVAILABLE TAG: 5
message PropertySpec {
// Must be lowercase, and will be matched case-insensitively.
optional string name = 1;
optional bool mandatory = 2;
// This would be a oneof, but this file only uses features in protobuf 2.5.0.
// begin oneof {
// Must be lowercase, and will be matched case-insensitively.
optional string value = 3;
optional double value_double = 4;
// } end oneof
}
// NEXT AVAILABLE TAG: 2
message PropertySpecList {
repeated PropertySpec properties = 1;
}
// Used for validating urls in attribute values (such as href/src/srcset).
// NEXT AVAILABLE TAG: 5
message UrlSpec {
// protocol must be in lowercase (e.g. "javascript" not "JavaScript").
repeated string protocol = 1;
optional bool allow_relative = 2 [default = true];
// Whether the empty string '' is allowed for this URL value.
optional bool allow_empty = 3 [default = false];
// Deprecated fields, do not reuse.
// reserved 4;
}
// NEXT AVAILABLE TAG: 4
message CssDeclaration {
// The name of the declaration (e.g. display). Use lower-case attribute names
// only.
optional string name = 1;
// This would be a oneof, but this file only uses features in protobuf 2.5.0.
// begin oneof {
// The valid values of the declaration (e.g. block).
repeated string value_casei = 2;
optional string value_regex_casei = 3;
// } end oneof
}
// Attributes that are not covered by at least one of these specs are
// disallowed. Within a given context (e.g., for a given TagSpec),
// names are unique.
// NEXT AVAILABLE TAG: 29
message AttrSpec {
// If provided, the Type Identifier(s) that either enable or disable
// this AttrSpec. If a Type Identifier is in enabled_by then this
// AttrSpec will be used in validating parsed documents with that Type
// Identifier. If a Type Identifier is in disabled_by then this
// AttrSpec will not be used in validating parsed documents with that
// Type Identifier. An AttrSpec can not have both enabled_by and disabled_by
// set.
repeated string enabled_by = 23;
repeated string disabled_by = 24;
// Use lower-case attribute names only.
optional string name = 1;
repeated string alternative_names = 2;
optional bool mandatory = 3;
// Within the context of the tag, *exactly one* of the attributes tagged
// with this identifier must be present. Per convention, this identifier
// should list the tags participating in the mandatory oneof:
// e.g. mandatory_oneof: "['foo', 'bar']"
optional string mandatory_oneof = 12;
// Within the context of the tag, *at least one* of the attributes tagged
// with this identifier must be present. Per convention, this identifier
// should list the tags participating in the mandatory oneof:
// e.g. mandatory_oneof: "['foo', 'bar']"
optional string mandatory_anyof = 21;
// This would be a oneof, but this file only uses features in protobuf 2.5.0.
// begin oneof {
// If none of these are set, any value is accepted unless
// disallowed_value_regex is set. Note that prior to comparing, the
// attributes in a given HTML document will be unescaped.
// The attribute value must be equal to the value in this field.
repeated string value = 4; // case sensitive
repeated string value_casei = 18; // case insensitive
optional string value_regex = 15; // case sensitive
optional string value_regex_casei = 5; // case insensitive
optional UrlSpec value_url = 14;
// validates against a list of properties (see PropertySpec).
optional PropertySpecList value_properties = 11;
// If set, the attribute value will be evaluated using the matching document
// level CSS rules. This flag is used for `style` attributes. If
// `value_doc_css` is set, only non-SVG css is applied. If `value_doc_css_svg`
// is set, SVG-specific CSS rules are also allowed for this attribute value.
optional bool value_doc_css = 27;
optional bool value_doc_svg_css = 28;
// } end oneof
// These two fields specify that values from one AttrSpec refer to values from
// another AttrSpec elsewhere on the page; validator will verify the
// references are not "dangling". These references may appear before or after
// their referents.
//
// For example, in the "id" AttrSpec in the "template" TagSpec, we have:
// add_value_to_set: TEMPLATE_IDS
// and in any "template" AttrSpec, we have:
// value_oneof_set: TEMPLATE_IDS
// NEXT AVAILABLE TAG: 3
enum ValueSet {
UNKNOWN_VALUESET = 0; // Never used
TEMPLATE_IDS = 1; // <template id> values
AMP_SCRIPT_IDS = 2; // <script id> values, referenced by <amp-script>
}
optional ValueSet add_value_to_set = 25;
optional ValueSet value_oneof_set = 26;
optional AttrTriggerSpec trigger = 16;
// If set, then the attribute value may not match this regex, which is
// always applied case-insensitively and as a partial match.
optional string disallowed_value_regex = 6;
// If set, generates a DEPRECATED_ATTR error with severity WARNING.
// The value of the deprecation field indicates what to use instead,
// e.g. the name of an attribute or tag.
optional string deprecation = 7;
// If provided, a URL which links to the AMP HTML spec for this deprecation.
optional string deprecation_url = 8;
// Valid CSS declarations.
repeated CssDeclaration css_declaration = 20;
enum DispatchKeyType {
// Indicates that the attribute does not form a dispatch key.
NONE_DISPATCH = 0;
// Indicates that the name of the attribute alone forms a dispatch key.
NAME_DISPATCH = 1;
// Indicates that the name + value of the attribute forms a dispatch key.
NAME_VALUE_DISPATCH = 2;
// Indicates that the name + value + mandatory parent forms a dispatch key.
NAME_VALUE_PARENT_DISPATCH = 3;
}
// If set true, the TagSpec containing this AttrSpec will be evaluated first
// for any encountered tag which matches the tag name and this attribute spec.
// May only be set for an AttrSpec where mandatory=true and type matches those
// specified in the comments of DispatchKeyType above.
optional DispatchKeyType dispatch_key = 13 [default = NONE_DISPATCH];
// If set to true, the TagSpec containing this AttrSpec implicitly has this
// attribute and the attribute is considered valid.
optional bool implicit = 17 [default = false];
// If set, this attr is considered part of an amp extended component, and
// requires that the named extended component script tag is present on the
// page.
repeated string requires_extension = 19;
// If set, this attr is invalid unless the current tag has an ancestor
// tag which set one or more of the required markers.
optional AncestorMarker requires_ancestor = 22;
}
// Some tags share several attributes, so they're identified by unique key
// (see the attr_lists map in ValidatorRules).
// NEXT AVAILABLE TAG: 3
message AttrList {
optional string name = 1;
repeated AttrSpec attrs = 2;
}
// A list of allowed tags for descendants of any level (children, grandchildren,
// great-grandchildren, etc).
// NEXT AVAILABLE TAG: 3
message DescendantTagList {
optional string name = 1;
repeated string tag = 2;
}
// Some style blocks share long lists of declarations, so they're identified by
// unique key.
// NEXT AVAILABLE TAG: 3
message DeclarationList {
optional string name = 1;
repeated CssDeclaration declaration = 2;
}
// Regex which, if matches the cdata of a tag, causes the tag validation to
// fail.
// NEXT AVAILABLE TAG: 3
message DisallowedCDataRegex {
// Syntax is partial match, use ^ and $ if you want global match.
optional string regex = 1;
optional string error_message = 2;
}
// This spec is used when parsing a media query inside a CSS @media rule.
// NEXT AVAILABLE TAG: 5
message MediaQuerySpec {
// If issues_as_error is true, then parsing errors and invalid
// types / features will be treated as validator errors, otherwise warnings.
optional bool issues_as_error = 1 [default = false];
// These are the media query types and features allowed within the stylesheet.
// http://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries#Syntax
repeated string type = 2;
repeated string feature = 3;
}
// This spec is used when parsing a CSS selector group as the prelude of a CSS
// qualified rule. For example "div.foo span.bar". If no SelectorSpec is
// provided, the selector groups are unconstrained.
// NEXT AVAILABLE TAG: 4
message SelectorSpec {
// For each SelectorSpec list provided a single list element value of "*"
// indicates that any value is allowed (ie: that feature is unconstrained).
// An empty list indicates that no value is allowed (ie: that feature is
// disallowed). Otherwise, the list values are the only allowed values.
// Allowed attribute selector names. For example `foo` in the selector
// `.a[foo=bar]`.
repeated string attribute_name = 1;
// Allowed pseudo class names. For example `checked` in `.a:checked`.
repeated string pseudo_class = 2;
// Allowed pseudo element names. For example `before` in `.a::before`.
repeated string pseudo_element = 3;
}
// This spec is used by our CSS parser to determine what AT rules are allowed
// in the CSS spec. The term 'rule' here refers to the AT Rule in CSS, not a
// validation rule.
// NEXT AVAILABLE TAG: 4
message AtRuleSpec {
// Name of the AT rule to parse. Do not include the '@' symbol (e.g. '@media'
// should be encoded as 'media'.
optional string name = 1;
// A MediaQuerySpec may only be set for an AtRuleSpec with the name
// "media". If not set, media queries will be left unparsed, so no errors or
// warnings about them will be reported.
optional MediaQuerySpec media_query_spec = 3;
}
// NEXT AVAILABLE TAG: 10
message CssSpec {
// Spec for how to parse CSS AT rules, one per AT rule. Must not contain
// duplicate names, and must contain at least one entry for the default.
repeated AtRuleSpec at_rule_spec = 1;
// Enables checks specific to the draft A4A specification.
// TODO(powdercloud): Make this more generic.
optional bool validate_amp4ads = 5;
// Enables checks specific to the style[keyframes] specification.
// TODO(chenshay): Make this more generic.
optional bool validate_keyframes = 6;
// Any declaration listed here are allowed.
repeated string declaration = 7;
// If false, declarations tagged with `!important` are considered errors.
// Most AMP stylesheets disallow `!important` to reserve this override
// for AMP's own styles.
optional bool allow_important = 8 [default = false];
optional SelectorSpec selector_spec = 9;
// Deprecated fields, do not reuse.
// reserved 3, 4;
}
// NEXT AVAILABLE TAG: 12
message CdataSpec {
// If set, the cdata contents cannot be greater than this length, in bytes. A
// value of -2 (default) indicates that there is no limit (unlimited). A value
// of -1 will always cause validation failure on match. -1 is used to
// implement the `amp-custom-length-check` attribute:
// (https://github.com/ampproject/amphtml/issues/22315#issuecomment-496681165)
optional int32 max_bytes = 1 [default = -2];
// If provided, a URL which linking to a section / sentence in the
// AMP HTML spec.
optional string max_bytes_spec_url = 2;
// This would be a oneof, but this file only uses features in protobuf 2.5.0.
// begin oneof {
// If non-empty, the text between the start / end tag must match this value.
optional string mandatory_cdata = 3;
// If non-empty, the text between the start / end tag must match this regex.
optional string cdata_regex = 6;
// If at least one CssSpec is provided, this cdata field will be parsed
// as CSS3, and any parsing errors will become validation errors.
optional CssSpec css_spec = 7;
// If set to true, then only whitespace may be in the cdata contents.
// This is useful for script tags that reference extensions etc.
optional bool whitespace_only = 8;
// } end oneof
// If any of these regexes match, then this cdata spec does not validate.
repeated DisallowedCDataRegex disallowed_cdata_regex = 4;
// If true, the contents of this tag's CDATA text will be counted against the
// document level DocCssSpec CSS lengths.
optional bool doc_css_bytes = 11;
// Deprecated fields, do not reuse.
// reserved 5, 9;
}
// Specifies which AMP Layouts are supported by a given element.
// For the purpose of the validator, this specifies which
// values for layout, height, and width attributes are allowed. Also see
// https://github.com/ampproject/amphtml/blob/main/docs/spec/amp-html-layout.md
// TODO(johannes): Make the error messages around layouts better. This
// may require revamping the documentation for elements and/or the above spec,
// so that a user gets more clearly informed about which layouts are
// applicable to a given tag, what happens when layout attribute or other
// attributes are not set, etc.
// NEXT AVAILABLE TAG: 4
message AmpLayout {
// NEXT AVAILABLE TAG: 10
enum Layout {
CONTAINER = 5;
FILL = 6;
FIXED = 2;
FIXED_HEIGHT = 3;
FLEX_ITEM = 7;
FLUID = 8;
INTRINSIC = 9;
NODISPLAY = 1;
RESPONSIVE = 4;
UNKNOWN = 0;
}
// Specifies which layouts are supported by this element.
repeated Layout supported_layouts = 1;
// Specifies whether this element has default dimensions. This corresponds
// to being allowlisted in naturalDimensions_ in
// https://github.com/ampproject/amphtml/blob/main/src/static-layout.js.
optional bool defines_default_width = 2;
optional bool defines_default_height = 3;
}
// An AncestorMarker is a state maintained on the stack of matching tags.
// When a TagSpec with an AncestorMarker matches, this Marker is placed on the
// stack until the matched html tag is popped from the stack. Other rules may be
// triggered by the presence of a specific AncestorMarker on the stack.
// NEXT AVAILABLE TAG: 2
message AncestorMarker {
// NEXT AVAILABLE TAG: 2
enum Marker {
UNKNOWN = 0;
// Set by <amp-sidebar> tags to allow autoscroll attributes on descendants.
// See https://github.com/ampproject/amphtml/pull/20524 for more context.
AUTOSCROLL = 1;
}
repeated Marker marker = 1;
}
// TagSpec::child_tags uses this configuration to specify which child tags
// are expected for a specific tag.
//
// Matching child tags is done by tag name, while the parent is
// matched by TagSpec. The reason for this is that matching by tag
// spec name would produce less useful error messages, because we want
// to be able to produce a good message even if the tag spec name
// could not be determined because the enclosed child tag is invalid
// (no TagSpec matches). By doing a tag name match, we can produce a
// reasonable error regardless if a child tag was misplaced.
// NEXT AVAILABLE TAG: 5
message ChildTagSpec {
// Unless set to -1 (the default), the parent tag must have exactly
// |mandatory_num_child_tags| immediate child tags.
optional int32 mandatory_num_child_tags = 1 [default = -1];
// If at least one tag name is specified, then the first child of the
// parent tag must have one of the provided names.
repeated string first_child_tag_name_oneof = 2;
// If at least one tag name is specified, then the child tags of
// the parent tag must have one of the provided tag names.
repeated string child_tag_name_oneof = 3;
// Unless set to -1 (the default), the parent tag must have a minimum of
// |mandatory_min_num_child_tags| immediate child tags.
optional int32 mandatory_min_num_child_tags = 4 [default = -1];
}
// TagSpecs and reference points.
//
// Any TagSpec may define a list of reference points via the
// TagSpec::reference_points field. These reference points specify how
// DOM elements that are children of this parent tag fulfill particular
// functionality. For instance, a widget (implemented as an AMP tag) may
// require a login reference point. Any valid AMP tag would be allowed,
// whether it's a clickable DIV or an AMP-IMG or a BUTTON, so long as
// it *also* conforms to the reference point specification. This
// specification is a TagSpec which does not define a name (the
// name is set to the special value '$REFERENCE_POINT'), but rather
// identifies the reference point with AttrSpec requirements. For instance,
// the login reference point may require that there be a login attribute,
// or some end-point attribute with a URL, or similar.
// Therefore, for any child tags of a tag that defines reference points,
// they are first matched against these reference points, and only
// then are they validated as regular tags against the TagSpecs that are
// not reference points while their reference point attributes are skipped.
// The complexity of this mechanism is unfortunate but reduces the markup
// required and makes CSS styling more convenient. Please see
// the amp-live-list specification for an example.
// NEXT AVAILABLE TAG: 4
message ReferencePoint {
// A tag spec identified by its TagSpec::spec_name which specifies how
// a specific functionality for the parent tag is assigned.
optional string tag_spec_name = 1;
// At least one of the child tags of the parent defining this
// reference point must match it.
optional bool mandatory = 2;
// At most one of the child tags of the parent defining this
// reference point must match it.
optional bool unique = 3;
}
// Specs specific to AMP Extensions. This is a field within TagSpec that
// replaces the standard tagspec list of attributes, requirements, etc.
// NEXT AVAILABLE TAG: 11
message ExtensionSpec {
// e.g. "amp-video". This is used both as the attribute value for the
// 'custom-element' attribute value as well as part of the 'src' attribute
// value.
optional string name = 1;
// e.g. "0.1", "1.0", "latest".
repeated string version = 2;
// If multiple TagSpecs for the same extension exist, separated by version,
// specify a version_name string to disambiguate their spec_names. For
// example, "v1.0" or "v0.1-0.2". This string will become part of the name
// used for referring to this extension in validator error messages.
optional string version_name = 9;
// deprecated_version must be a strict subset of version. If the version
// matches a deprecated_version, validation will emit a warning.
repeated string deprecated_version = 3;
// Bento supported versions (e.g. "1.0").
repeated string bento_supported_version = 10;
// Most extensions are custom-elements. For custom-template extensions, this
// value needs to be set true. E.g: amp-mustache.
// NEXT AVAILABLE TAG: 4
enum ExtensionType {
UNKNOWN = 0;
CUSTOM_ELEMENT = 1;
CUSTOM_TEMPLATE = 2;
HOST_SERVICE = 3;
}
optional ExtensionType extension_type = 8 [default = CUSTOM_ELEMENT];
// For older tags, we did not originally require that the tag only be included
// once, so those tags are exempted from the multiple inclusion ban.
optional bool deprecated_allow_duplicates = 6 [default = false];
// TagSpec.requires_extension will be set to the new extension's name on one
// or more TagSpecs that require that extension. This typically creates 2
// validation requirements:
// 1) If a tag is on the page whose TagSpec has the requires_extension
// field set, but that extension is not present, this is an error.
// (Usage requires extension).
// 2) If an extension is on the page, but no tags indicating usage of that
// extension via the required_extension field are on the page, this is an
// error. (Extension requires usage).
//
// The second requirement (extension requires usage) has a few exceptions:
// 1) For older extensions, implemented before these tagspec rules, we
// do not want to introduce a breaking change, so we exempt these
// extensions from the usage requirement. New extensions must use ERROR.
// 2) Some extensions, such as `amp-dynamic-css-classes`, do not have any
// associated tag in the document indicating usage. These extensions do
// not trigger warnings or errors.
// NEXT AVAILABLE TAG: 4
enum ExtensionUsageRequirement {
ERROR = 1;
// Exception for exempted extensions. #1 above.
EXEMPTED = 2;
// Exception for extensions with no usage-indicating tag. #2 above.
NONE = 3;
}
optional ExtensionUsageRequirement requires_usage = 7 [default = ERROR];
// Deprecated fields, do not reuse.
// reserved 4, 5;
}
// The HtmlFormat is the declared format in the top-level html tag, which
// prescribes a particular set of validation rules. This should be kept in sync
// with Request.HtmlFormat in
// github.com/ampproject/amppackager/transformer/request/request.proto.
message HtmlFormat {
// NEXT AVAILABLE TAG: 6
enum Code {
UNKNOWN_CODE = 0; // Never used
AMP = 1;
AMP4ADS = 2;
AMP4EMAIL = 3;
EXPERIMENTAL = 4; // Currently unused
}
// Deprecated fields, do not reuse.
// reserved 5;
}
// Tags that are not covered by at least one of these specs are disallowed.
// Some tags are mandatory. Note that the tag name is not unique, that is,
// there can be multiple tag specs covering the same name, e.g., for
// multiple meta tags (with different attributes).
// NEXT AVAILABLE TAG: 40
message TagSpec {
// The html_format field tells the validator for which html formats
// (ie: (<html ⚡> vs <html a4⚡>) this HTML TagSpec is allowed to validate.
// The repeated field is not allowed to be empty, it must have at least one
// HtmlFormat.
repeated HtmlFormat.Code html_format = 21;
// If provided, the Type Identifier(s) that either enable or disable
// this TagSpec. If a Type Identifier is in `enabled_by` then this
// TagSpec will be used in validating parsed documents which include that Type
// Identifier. If a Type Identifier is in `disabled_by` then this
// TagSpec will not be used in validating parsed documents which include that
// Type Identifier. A TagSpec can not have both `enabled_by` and `disabled_by`
// set.
repeated string enabled_by = 35;
repeated string disabled_by = 36;
// Use UPPER-CASE tag names only. If adding the same tag twice, then they must
// also have a spec_name string which is unique throughout all detail.
// Note: "$REFERENCE_POINT" is a special tag_name value.
// Reference points are partial tag specs which don't have a defined
// tag_name.
optional string tag_name = 1;
// If provided, the spec_name must be unique within the validator
// rules. This string forms a a unique id for this TagSpec. If not set, the
// tag_name field is used as the unique id. This string is not used in error
// messages, see descriptive_name for that.
optional string spec_name = 2;
// If `tag_name` is not a sufficient descriptor for error messages having to
// do with this tag spec, provide a `descriptive_name` value, which if present
// will be used in place of `tag_name`. Typically `descriptive_name` should
// include the tag_name in it, and should avoid using < and > in case
// downstream libraries of the validator fail to properly HTML escape rendered
// error strings.
optional string descriptive_name = 39;
// NamedId's are used to uniquely identify specific TagSpecs in the
// validator rules in a stable manner. Most TagSpecs have no set NamedId.
// If a TagSpec has a NamedId it must be unique. In other words, no two
// TagSpec's may have the same NamedId except for the NOT_SET (0) value.
// NEXT AVAILABLE TAG: 3
enum NamedId {
NOT_SET = 0;
// By convention, the first "word" in the Id should be the tag_name.
LINK_FONT_STYLESHEET = 1;
STYLE_AMP_CUSTOM = 2;
}
optional NamedId named_id = 33 [default = NOT_SET];
// If provided, this is a SCRIPT tag defining an amp custom element
// extension. The other fields, such as expected attributes, will be
// validated by the extension spec rules.
optional ExtensionSpec extension_spec = 27;
// If set, this tag is considered part of an amp extended component, and
// requires that the named extended component script tag is present on the
// page.
repeated string requires_extension = 28;
// If true, a tag conforming to this tag spec must occur at least once
// within the document.
optional bool mandatory = 3;
// A string identifying that this tag belongs to a set of alternative
// choices from which at least one needs to be satisfied.
optional string mandatory_alternatives = 4;
// If true, a tag conforming to this tag spec may occur at most once within
// the document.
optional bool unique = 5;
// If true, a tag conforming to this tag spec should occur at most once within
// the document. That is, unlike for unique, we'll emit a warning.
optional bool unique_warning = 25;
// If set to "$ROOT", this tag must be the root tag.
// If set to any other string, the tag must be the direct child of the
// specified mandatory parent tag.
optional string mandatory_parent = 6;
// If set, the tag must descend from (not necessarily direct parent of) the
// specified mandatory parent string which is either a tag name or a tag
// spec_name (e.g. tag.name = "!DOCTYPE" or tag.spec_name = "html doctype").
optional string mandatory_ancestor = 15;
// Use only for tags where mandatory_ancestor is set. If tag validation fails
// due to the mandatory_ancestor, and this field is set, then the error
// detail will suggest the tag specified here as an alternative to consider.
optional string mandatory_ancestor_suggested_alternative = 16;
// This tag may not descend from any tag with any of these tag names or tag
// spec_names (e.g. tag.name = "!DOCTYPE" or tag.spec_name = "html doctype").
repeated string disallowed_ancestor = 13;
// If set, all of the tag's descendants must be tags from the named list.
// A tag not in the named list will generate an error.
optional string descendant_tag_list = 29;
// If set, other tags - identified by their detail string - must be
// present as well or a warning will be issued (will not invalidate doc).
repeated string also_requires_tag_warning = 22;
// Expresses a generic condition which is satisfied if this tag is found. Used
// in combination with the `requires` attribute on a different tag.
repeated string satisfies_condition = 23;
// Expresses a generic condition which must be satisfied if this tag is found.
// Used in combination with the `satisfies` attributes on a different tag.
repeated string requires_condition = 24;
// The excludes field is a generic condition, which must not be satisfied if
// this tag is found. Otherwise a TAG_EXCLUDED_BY_TAG error will be generated.
// Used in combination with the `satisfies` attributes on a different tag.
repeated string excludes_condition = 32;
// If set, generates a DEPRECATED_TAG error with severity WARNING.
// The value of the deprecation field indicates what to use instead,
// e.g. the name of a tag.
optional string deprecation = 17;
// If provided, a URL which links to the AMP HTML spec for this deprecation.
optional string deprecation_url = 18;
// This TagSpec will only validate against attributes explicitly
// listed within the TagSpec (attrs and attr_lists). No attributes
// from $GLOBAL_ATTRS and $AMP_LAYOUT_ATTRS are valid unless explicitly
// added as an attribute within the TagSpec. The field `amp_layout` is not
// allowed to be set when `explicit_attrs_only` is true.
optional bool explicit_attrs_only = 34 [default = false];
// Attribute specifications related to this tag.
repeated AttrSpec attrs = 7;
// Top level attr lists of shared tags, identified by unique key
// (see attr_lists map in ValidatorRules).
repeated string attr_lists = 8;
// Note that these are evaluated after a particular TagSpec
// has been evaluated. Unlike other checks in this TagSpec, we
// no longer have the ability to fall back on a different TagSpec.
optional CdataSpec cdata = 12;
// Specifies which tags can be the child tags, that is, immediately children
// of this tag in the document.
optional ChildTagSpec child_tags = 19;
// If set to true, this tag cannot have any siblings.
optional bool siblings_disallowed = 30 [default = false];
// If set to true, this tag must be the last child of its parent.
optional bool mandatory_last_child = 31 [default = false];
// The reference_points defined by this TagSpec instance determine how
// specific child tags are identified. Please see the comment for the
// ReferencePoint message.
repeated ReferencePoint reference_points = 20;
// If provided, a URL which linking to a section / sentence in the
// AMP HTML spec. If a TagSpec contains a requires_extension field,
// spec_url will be inherited from the named extension, unless overridden
// by the setting it here.
optional string spec_url = 10;
// If set, specifies which AMP Layouts are supported by this element.
optional AmpLayout amp_layout = 11;
// If set, triggers related validation rules for descendants of this tag.
optional AncestorMarker mark_descendants = 38;
// Deprecated fields, do not reuse.
// reserved 14, 26;
}
// Exactly one DocSpec will match each AMP document. This spec defines some
// default rules for the entire document scoped by it's HtmlFormat and any
// Type Identifiers.
// NEXT AVAILABLE TAG: 6
message DocSpec {
// The html_format field tells the validator for which html formats
// (ie: (<html ⚡> vs <html a4⚡>) this DocSpec is defined for.
repeated HtmlFormat.Code html_format = 1;
// If a Type Identifier is in enabled_by then this DocSpec will be used
// in validating parsed documents with that Type Identifier. If a Type
// Identifier is in disabled_by then this DocSpec will not be used in
// validating parsed documents with that Type Identifier. An DocSpec can
// not have both enabled_by and disabled_by set.
repeated string enabled_by = 2;
repeated string disabled_by = 3;
// If set, the entire document's content cannot be greater than this length,
// in bytes. A value of -2 (default) indicates that there is no limit
// (unlimited).
optional int32 max_bytes = 4 [default = -2];
// If provided, a URL linking to a section / sentence in the AMP HTML spec.
optional string max_bytes_spec_url = 5;
}
// Exactly one DocCssSpec will match each AMP document. This spec defines the
// default css rules for style attributes and publisher style tags across the
// entire document. Rules for specific tags may be overridden by those tags.
// NEXT AVAILABLE TAG: 20
message DocCssSpec {
// The html_format field tells the validator for which html formats
// (ie: (<html ⚡> vs <html a4⚡>) this DocCssSpec is defined for.
repeated HtmlFormat.Code html_format = 1;
// If a Type Identifier is in enabled_by then this DocCssSpec will be used
// in validating parsed documents with that Type Identifier. If a Type
// Identifier is in disabled_by then this DocCssSpec will not be used in
// validating parsed documents;: with that Type Identifier. An DocCssSpec can
// not have both enabled_by and disabled_by set.
repeated string enabled_by = 2;
repeated string disabled_by = 3;
// If provided, a URL linking to a section / sentence in the AMP HTML spec.
optional string spec_url = 4;
// Due to a bug, we allowed unlimited doc-level and per-inline-style bytes
// for CSS in non-AMP formats. To avoid breaking pages, some formats will
// only emit a warning for exceeding `max_bytes` and
// `max_bytes_per_inline_style`.
optional bool max_bytes_is_warning = 18 [default = false];
// If set, the combined style amp-custom cdata contents and all inline style
// contents cannot be greater than this length, in bytes. A value of -2
// (default) indicates that there is no limit (unlimited). A value of -1 will
// always cause validation failure.
optional int32 max_bytes = 5 [default = -2];
// If set, the inline style content (per use) cannot be greater than this
// length, in bytes.
optional int32 max_bytes_per_inline_style = 6 [default = -1];
// If false, bytes inside URLs are not included in the byte calculation for
// `max_bytes`. This is used for handling signed exchange transformations
// which can potentially take the number of bytes over the 75,000 byte limit
// due to rewriting URLs to point at an AMP Cache.
optional bool url_bytes_included = 7 [default = true];
// If provided, a URL linking to a section / sentence in the AMP HTML spec.
optional string max_bytes_spec_url = 8;
// If true, all declarations are allowed in style tags and inline style
// attributes, regardless of the contents of the `declaration` list.
optional bool allow_all_declaration_in_style = 10 [default = false];
// If true, all variants of declarations that are vendor prefixes are allowed.
// for example, if `gradient` is an allowed declaration and this is true, then
// `-webkit-gradient` is also an allowed declaration.
optional bool expand_vendor_prefixes = 19;
// Any declaration listed here is allowed in custom style tags and style
// attributes in any tag.
repeated CssDeclaration declaration = 11;
// In addition to those listed in 'declaration', any declaration listed here
// is allowed in style attributes for SVG elements.
repeated CssDeclaration declaration_svg = 12;
// Top level lists of shared declarations, identified by unique key.
repeated string declaration_list = 13;
// Top level lists of shared declarations, identified by unique key.
repeated string declaration_list_svg = 14;
// URLs found within CSS are checked against this spec.
optional UrlSpec image_url_spec = 15;
optional UrlSpec font_url_spec = 16;
// If false, declarations tagged with `!important` are considered errors.
// Most AMP stylesheets disallow `!important` to reserve this override
// for AMP's own styles.
optional bool allow_important = 17 [default = false];
}
// Top level message - start reading here.
// The validator knows about a set of tag specifications.
// NEXT AVAILABLE TAG: 22
message ValidatorRules {
repeated TagSpec tags = 1;
repeated AttrList attr_lists = 7;
// The min file revision for validator.cc which can digest this file.
optional int32 min_validator_revision_required = 4 [deprecated = true];
// See comment in validator.protoascii.
optional int32 spec_file_revision = 6 [deprecated = true, default = -1];
// Spec URL for information about mustache templates.
optional string template_spec_url = 8;
// Spec URL for information about styles and amp-custom stylesheet
optional string styles_spec_url = 15;
// Spec URL for information about script tags.
optional string script_spec_url = 17;
repeated ErrorFormat error_formats = 9;
repeated ErrorSpecificity error_specificity = 13;
repeated DescendantTagList descendant_tag_list = 16;
// The DocSpec rules are scoped by the document's HtmlFormat and Type
// Identifiers and defined within each DocSpec.
repeated DocSpec doc = 21;
repeated DocCssSpec css = 19;
repeated DeclarationList declaration_list = 20;
// Deprecated fields, do not reuse.
// reserved 2, 5, 11, 12, 14, 18;
}
// This feature was removed in October 2019, however there are still
// some callers that expect an ErrorCategory to be set. Do not rely
// on this in new code.
// TODO(#25188): Remove ErrorCategory completely.
message ErrorCategory {
enum Code {
UNKNOWN = 0;
}
}
// We record validation errors in a structured form, so that they can be
// worked with in code - e.g., to provide translated messages.
// In the Javascript implementation (validator.js), you may find
// the amp.validator.renderErrorMessage function which will make a
// human-readable string from the structured form. It should be easy to port
// this to other languages as needed; for instance Google has implementations
// in C++, Java, and for templates used in some frontends.
// NEXT AVAILABLE TAG: 10
message ValidationError {
// NEXT AVAILABLE TAG: 5
enum Severity {
UNKNOWN_SEVERITY = 0;
// A document with at least one error of this severity fails validation.
ERROR = 1;
// A document may have warnings and still pass validation.
WARNING = 4;
// DO NOT REASSIGN the previously used values 2, 3.
}
optional Severity severity = 6 [default = ERROR];
// NEXT AVAILABLE TAG: 124
enum Code {
UNKNOWN_CODE = 0;
INVALID_DOCTYPE_HTML = 111;
MANDATORY_TAG_MISSING = 1;
TAG_REQUIRED_BY_MISSING = 24;
WARNING_TAG_REQUIRED_BY_MISSING = 76;
TAG_EXCLUDED_BY_TAG = 101;
WARNING_EXTENSION_UNUSED = 79;
EXTENSION_UNUSED = 84;
WARNING_EXTENSION_DEPRECATED_VERSION = 80;
INVALID_EXTENSION_VERSION = 122;
INVALID_EXTENSION_PATH = 123;
NON_LTS_SCRIPT_AFTER_LTS = 112;
LTS_SCRIPT_AFTER_NON_LTS = 113;
INCORRECT_SCRIPT_RELEASE_VERSION = 119;
DISALLOWED_AMP_DOMAIN = 121;
ATTR_REQUIRED_BUT_MISSING = 61;
DISALLOWED_TAG = 2;
GENERAL_DISALLOWED_TAG = 51;
DISALLOWED_SCRIPT_TAG = 88;
DISALLOWED_ATTR = 3;
DISALLOWED_STYLE_ATTR = 81;
INVALID_ATTR_VALUE = 4;
DUPLICATE_ATTRIBUTE = 94;
ATTR_VALUE_REQUIRED_BY_LAYOUT = 27;
MISSING_LAYOUT_ATTRIBUTES = 105;
IMPLIED_LAYOUT_INVALID = 22;
SPECIFIED_LAYOUT_INVALID = 26;
MANDATORY_ATTR_MISSING = 5;
MANDATORY_ONEOF_ATTR_MISSING = 28;
MANDATORY_ANYOF_ATTR_MISSING = 104;
DUPLICATE_DIMENSION = 60;
DUPLICATE_UNIQUE_TAG = 6;
DUPLICATE_UNIQUE_TAG_WARNING = 77;
WRONG_PARENT_TAG = 7;
STYLESHEET_TOO_LONG = 50;
STYLESHEET_AND_INLINE_STYLE_TOO_LONG = 102;
INLINE_STYLE_TOO_LONG = 103;
INLINE_SCRIPT_TOO_LONG = 118;
MANDATORY_CDATA_MISSING_OR_INCORRECT = 9;
CDATA_VIOLATES_DENYLIST = 30;
NON_WHITESPACE_CDATA_ENCOUNTERED = 82;
INVALID_JSON_CDATA = 106;
DEPRECATED_ATTR = 11;
DEPRECATED_TAG = 12;
MANDATORY_PROPERTY_MISSING_FROM_ATTR_VALUE = 14;
INVALID_PROPERTY_VALUE_IN_ATTR_VALUE = 15;
MISSING_URL = 35;
INVALID_URL = 36;
INVALID_URL_PROTOCOL = 37;
DISALLOWED_DOMAIN = 62;
DISALLOWED_RELATIVE_URL = 49;
DISALLOWED_PROPERTY_IN_ATTR_VALUE = 16;
MUTUALLY_EXCLUSIVE_ATTRS = 17;
UNESCAPED_TEMPLATE_IN_ATTR_VALUE = 18;
TEMPLATE_PARTIAL_IN_ATTR_VALUE = 19;
TEMPLATE_IN_ATTR_NAME = 20;
INCONSISTENT_UNITS_FOR_WIDTH_AND_HEIGHT = 21;
DISALLOWED_TAG_ANCESTOR = 23;
MANDATORY_LAST_CHILD_TAG = 89;
MANDATORY_TAG_ANCESTOR = 31;
MANDATORY_TAG_ANCESTOR_WITH_HINT = 32;
ATTR_DISALLOWED_BY_IMPLIED_LAYOUT = 33;
ATTR_DISALLOWED_BY_SPECIFIED_LAYOUT = 34;
INCORRECT_NUM_CHILD_TAGS = 56;
INCORRECT_MIN_NUM_CHILD_TAGS = 85;
DISALLOWED_CHILD_TAG_NAME = 57;
DISALLOWED_FIRST_CHILD_TAG_NAME = 58;
DISALLOWED_MANUFACTURED_BODY = 64;
CHILD_TAG_DOES_NOT_SATISFY_REFERENCE_POINT = 66;
MANDATORY_REFERENCE_POINT_MISSING = 67;
DUPLICATE_REFERENCE_POINT = 68;
TAG_NOT_ALLOWED_TO_HAVE_SIBLINGS = 87;
TAG_REFERENCE_POINT_CONFLICT = 69;
CHILD_TAG_DOES_NOT_SATISFY_REFERENCE_POINT_SINGULAR = 70;
// TODO(gregable): Fix this spelling error: 'precede'
BASE_TAG_MUST_PRECEED_ALL_URLS = 78;
MISSING_REQUIRED_EXTENSION = 83;
ATTR_MISSING_REQUIRED_EXTENSION = 97;
DOCUMENT_TOO_COMPLEX = 86;
INVALID_UTF8 = 96;
DOCUMENT_SIZE_LIMIT_EXCEEDED = 108;
DEV_MODE_ONLY = 109;
AMP_EMAIL_MISSING_STRICT_CSS_ATTR = 120;
VALUE_SET_MISMATCH = 110;
CSS_SYNTAX_INVALID_AT_RULE = 29;
CSS_SYNTAX_STRAY_TRAILING_BACKSLASH = 38;
CSS_SYNTAX_UNTERMINATED_COMMENT = 39;
CSS_SYNTAX_UNTERMINATED_STRING = 40;
CSS_SYNTAX_BAD_URL = 41;
CSS_SYNTAX_EOF_IN_PRELUDE_OF_QUALIFIED_RULE = 42;
CSS_SYNTAX_INVALID_DECLARATION = 43;
CSS_SYNTAX_INCOMPLETE_DECLARATION = 44;
CSS_SYNTAX_ERROR_IN_PSEUDO_SELECTOR = 45;
CSS_SYNTAX_MISSING_SELECTOR = 46;
CSS_SYNTAX_NOT_A_SELECTOR_START = 47;
CSS_SYNTAX_UNPARSED_INPUT_REMAINS_IN_SELECTOR = 48;
CSS_SYNTAX_MISSING_URL = 52;
CSS_SYNTAX_INVALID_URL = 53;
CSS_SYNTAX_INVALID_URL_PROTOCOL = 54;
CSS_SYNTAX_DISALLOWED_DOMAIN = 63;
CSS_SYNTAX_DISALLOWED_RELATIVE_URL = 55;
CSS_SYNTAX_INVALID_ATTR_SELECTOR = 59;
CSS_SYNTAX_INVALID_PROPERTY = 90;
CSS_SYNTAX_INVALID_PROPERTY_NOLIST = 95;
CSS_SYNTAX_QUALIFIED_RULE_HAS_NO_DECLARATIONS = 91;
CSS_SYNTAX_DISALLOWED_QUALIFIED_RULE_MUST_BE_INSIDE_KEYFRAME = 92;
CSS_SYNTAX_DISALLOWED_KEYFRAME_INSIDE_KEYFRAME = 93;
CSS_SYNTAX_MALFORMED_MEDIA_QUERY = 98;
CSS_SYNTAX_DISALLOWED_MEDIA_TYPE = 99;
CSS_SYNTAX_DISALLOWED_MEDIA_FEATURE = 100;
CSS_SYNTAX_DISALLOWED_ATTR_SELECTOR = 114;
CSS_SYNTAX_DISALLOWED_PSEUDO_CLASS = 115;
CSS_SYNTAX_DISALLOWED_PSEUDO_ELEMENT = 116;
CSS_SYNTAX_DISALLOWED_PROPERTY_VALUE = 71;
CSS_SYNTAX_DISALLOWED_IMPORTANT = 117;
CSS_EXCESSIVELY_NESTED = 107;
// The following codes are currently used only by A4A CSS validation.
CSS_SYNTAX_DISALLOWED_PROPERTY_VALUE_WITH_HINT = 72;
CSS_SYNTAX_PROPERTY_DISALLOWED_WITHIN_AT_RULE = 73;
CSS_SYNTAX_PROPERTY_DISALLOWED_TOGETHER_WITH = 74;
CSS_SYNTAX_PROPERTY_REQUIRES_QUALIFICATION = 75;
// Deprecated fields, do not reuse.
// reserved 13;
}
optional Code code = 1;
optional int32 line = 2 [default = 1];
optional int32 col = 3;
optional string spec_url = 5;
repeated string params = 7;
// This field is deprecated. Do not use.
optional ErrorCategory.Code category = 8;
// Used only in JavaScript, if an error is emitted for a specific HTML tag and
// if that HTML tag has an attribute named data-amp-report-test, this string
// will be set and contain the value found for that attribute. This is used
// in tests to match specific errors to specific tags in the test cases. It
// is not a rendered value.
optional string data_amp_report_test_value = 9;
// Deprecated fields, do not reuse.
// reserved 4;
}