/[suikacvs]/markup/html/whatpm/Whatpm/CSS/Parser.pm
Suika

Diff of /markup/html/whatpm/Whatpm/CSS/Parser.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.21 by wakaba, Thu Jan 3 13:51:41 2008 UTC revision 1.22 by wakaba, Fri Jan 4 05:36:36 2008 UTC
# Line 448  my $default_serializer = sub { Line 448  my $default_serializer = sub {
448      return $value->[1]; ## TODO: big or small number cases?      return $value->[1]; ## TODO: big or small number cases?
449    } elsif ($value->[0] eq 'DIMENSION') {    } elsif ($value->[0] eq 'DIMENSION') {
450      return $value->[1] . $value->[2]; ## NOTE: This is what browsers do.      return $value->[1] . $value->[2]; ## NOTE: This is what browsers do.
451      } elsif ($value->[0] eq 'PERCENTAGE') {
452        return $value->[1] . '%';
453    } elsif ($value->[0] eq 'KEYWORD') {    } elsif ($value->[0] eq 'KEYWORD') {
454      return $value->[1];      return $value->[1];
455    } elsif ($value->[0] eq 'URI') {    } elsif ($value->[0] eq 'URI') {
# Line 1279  $Prop->{'margin-top'} = { Line 1281  $Prop->{'margin-top'} = {
1281      my ($self, $prop_name, $tt, $t, $onerror) = @_;      my ($self, $prop_name, $tt, $t, $onerror) = @_;
1282    
1283      ## NOTE: Used for 'margin-top', 'margin-right', 'margin-bottom',      ## NOTE: Used for 'margin-top', 'margin-right', 'margin-bottom',
1284      ## 'margin-left', 'top', 'right', 'bottom', and 'left'.      ## 'margin-left', 'top', 'right', 'bottom', 'left', 'padding-top',
1285        ## 'padding-right', 'padding-bottom', 'padding-left',
1286        ## 'border-top-width', 'border-right-width', 'border-bottom-width',
1287        ## and 'border-left-width'.
1288    
1289      my $sign = 1;      my $sign = 1;
1290      if ($t->{type} == MINUS_TOKEN) {      if ($t->{type} == MINUS_TOKEN) {
1291        $t = $tt->get_next_token;        $t = $tt->get_next_token;
1292        $sign = -1;        $sign = -1;
1293      }      }
1294        my $allow_negative = $Prop->{$prop_name}->{allow_negative};
1295    
1296      if ($t->{type} == DIMENSION_TOKEN) {      if ($t->{type} == DIMENSION_TOKEN) {
1297        my $value = $t->{number} * $sign;        my $value = $t->{number} * $sign;
1298        my $unit = lc $t->{value}; ## TODO: case        my $unit = lc $t->{value}; ## TODO: case
1299        $t = $tt->get_next_token;        $t = $tt->get_next_token;
1300        if ($length_unit->{$unit}) {        if ($length_unit->{$unit} and ($allow_negative or $value >= 0)) {
1301          return ($t, {$prop_name => ['DIMENSION', $value, $unit]});          return ($t, {$prop_name => ['DIMENSION', $value, $unit]});
1302        }        }
1303      } elsif ($t->{type} == PERCENTAGE_TOKEN) {      } elsif ($t->{type} == PERCENTAGE_TOKEN) {
1304        my $value = $t->{number} * $sign;        my $value = $t->{number} * $sign;
1305        $t = $tt->get_next_token;        $t = $tt->get_next_token;
1306        return ($t, {$prop_name => ['PERCENTAGE', $value]});        return ($t, {$prop_name => ['PERCENTAGE', $value]})
1307              if $allow_negative or $value >= 0;
1308      } elsif ($t->{type} == NUMBER_TOKEN and      } elsif ($t->{type} == NUMBER_TOKEN and
1309               ($self->{unitless_px} or $t->{number} == 0)) {               ($self->{unitless_px} or $t->{number} == 0)) {
1310        my $value = $t->{number} * $sign;        my $value = $t->{number} * $sign;
1311        $t = $tt->get_next_token;        $t = $tt->get_next_token;
1312        return ($t, {$prop_name => ['DIMENSION', $value, 'px']});        return ($t, {$prop_name => ['DIMENSION', $value, 'px']})
1313              if $allow_negative or $value >= 0;
1314      } elsif ($sign > 0 and $t->{type} == IDENT_TOKEN) {      } elsif ($sign > 0 and $t->{type} == IDENT_TOKEN) {
1315        my $value = lc $t->{value}; ## TODO: case        my $value = lc $t->{value}; ## TODO: case
1316        $t = $tt->get_next_token;        $t = $tt->get_next_token;
1317        if ($value eq 'auto') {        if ($Prop->{$prop_name}->{keyword}->{$value}) {
1318          return ($t, {$prop_name => ['KEYWORD', $value]});                  return ($t, {$prop_name => ['KEYWORD', $value]});        
1319        } elsif ($value eq 'inherit') {        } elsif ($value eq 'inherit') {
1320          return ($t, {$prop_name => ['INHERIT']});          return ($t, {$prop_name => ['INHERIT']});
# Line 1318  $Prop->{'margin-top'} = { Line 1326  $Prop->{'margin-top'} = {
1326                 token => $t);                 token => $t);
1327      return ($t, undef);      return ($t, undef);
1328    },    },
1329      allow_negative => 1,
1330      keyword => {auto => 1},
1331    serialize => $default_serializer,    serialize => $default_serializer,
1332    initial => ['DIMENSION', 0, 'px'],    initial => ['DIMENSION', 0, 'px'],
1333    #inherited => 0,    #inherited => 0,
# Line 1331  $Prop->{'margin-bottom'} = { Line 1341  $Prop->{'margin-bottom'} = {
1341    dom => 'margin_bottom',    dom => 'margin_bottom',
1342    key => 'margin_bottom',    key => 'margin_bottom',
1343    parse => $Prop->{'margin-top'}->{parse},    parse => $Prop->{'margin-top'}->{parse},
1344      allow_negative => 1,
1345      keyword => {auto => 1},
1346    serialize => $default_serializer,    serialize => $default_serializer,
1347    initial => ['DIMENSION', 0, 'px'],    initial => ['DIMENSION', 0, 'px'],
1348    #inherited => 0,    #inherited => 0,
# Line 1344  $Prop->{'margin-right'} = { Line 1356  $Prop->{'margin-right'} = {
1356    dom => 'margin_right',    dom => 'margin_right',
1357    key => 'margin_right',    key => 'margin_right',
1358    parse => $Prop->{'margin-top'}->{parse},    parse => $Prop->{'margin-top'}->{parse},
1359      allow_negative => 1,
1360      keyword => {auto => 1},
1361    serialize => $default_serializer,    serialize => $default_serializer,
1362    initial => ['DIMENSION', 0, 'px'],    initial => ['DIMENSION', 0, 'px'],
1363    #inherited => 0,    #inherited => 0,
# Line 1357  $Prop->{'margin-left'} = { Line 1371  $Prop->{'margin-left'} = {
1371    dom => 'margin_left',    dom => 'margin_left',
1372    key => 'margin_left',    key => 'margin_left',
1373    parse => $Prop->{'margin-top'}->{parse},    parse => $Prop->{'margin-top'}->{parse},
1374      allow_negative => 1,
1375      keyword => {auto => 1},
1376    serialize => $default_serializer,    serialize => $default_serializer,
1377    initial => ['DIMENSION', 0, 'px'],    initial => ['DIMENSION', 0, 'px'],
1378    #inherited => 0,    #inherited => 0,
# Line 1370  $Prop->{top} = { Line 1386  $Prop->{top} = {
1386    dom => 'top',    dom => 'top',
1387    key => 'top',    key => 'top',
1388    parse => $Prop->{'margin-top'}->{parse},    parse => $Prop->{'margin-top'}->{parse},
1389      allow_negative => 1,
1390      keyword => {auto => 1},
1391    serialize => $default_serializer,    serialize => $default_serializer,
1392    initial => ['KEYWORD', 'auto'],    initial => ['KEYWORD', 'auto'],
1393    #inherited => 0,    #inherited => 0,
# Line 1430  $Prop->{bottom} = { Line 1448  $Prop->{bottom} = {
1448    dom => 'bottom',    dom => 'bottom',
1449    key => 'bottom',    key => 'bottom',
1450    parse => $Prop->{'margin-top'}->{parse},    parse => $Prop->{'margin-top'}->{parse},
1451      allow_negative => 1,
1452      keyword => {auto => 1},
1453    serialize => $default_serializer,    serialize => $default_serializer,
1454    initial => ['KEYWORD', 'auto'],    initial => ['KEYWORD', 'auto'],
1455    #inherited => 0,    #inherited => 0,
# Line 1443  $Prop->{left} = { Line 1463  $Prop->{left} = {
1463    dom => 'left',    dom => 'left',
1464    key => 'left',    key => 'left',
1465    parse => $Prop->{'margin-top'}->{parse},    parse => $Prop->{'margin-top'}->{parse},
1466      allow_negative => 1,
1467      keyword => {auto => 1},
1468    serialize => $default_serializer,    serialize => $default_serializer,
1469    initial => ['KEYWORD', 'auto'],    initial => ['KEYWORD', 'auto'],
1470    #inherited => 0,    #inherited => 0,
# Line 1533  $Prop->{right} = { Line 1555  $Prop->{right} = {
1555  $Attr->{right} = $Prop->{right};  $Attr->{right} = $Prop->{right};
1556  $Key->{right} = $Prop->{right};  $Key->{right} = $Prop->{right};
1557    
1558  $Prop->{'padding-top'} = {  $Prop->{width} = {
1559    css => 'padding-top',    css => 'width',
1560    dom => 'padding_top',    dom => 'width',
1561    key => 'padding_top',    key => 'width',
1562      parse => $Prop->{'margin-top'}->{parse},
1563      #allow_negative => 0,
1564      keyword => {auto => 1},
1565      serialize => $default_serializer,
1566      initial => ['KEYWORD', 'auto'],
1567      #inherited => 0,
1568      compute => $compute_length,
1569          ## NOTE: See <http://suika.fam.cx/gate/2005/sw/width> for
1570          ## browser compatibility issues.
1571    };
1572    $Attr->{width} = $Prop->{width};
1573    $Key->{width} = $Prop->{width};
1574    
1575    $Prop->{'min-width'} = {
1576      css => 'min-width',
1577      dom => 'min_width',
1578      key => 'min_width',
1579      parse => $Prop->{'margin-top'}->{parse},
1580      #allow_negative => 0,
1581      #keyword => {},
1582      serialize => $default_serializer,
1583      initial => ['DIMENSION', 0, 'px'],
1584      #inherited => 0,
1585      compute => $compute_length,
1586    };
1587    $Attr->{min_width} = $Prop->{'min-width'};
1588    $Key->{min_width} = $Prop->{'min-width'};
1589    
1590    $Prop->{'max-width'} = {
1591      css => 'max-width',
1592      dom => 'max_width',
1593      key => 'max_width',
1594      parse => $Prop->{'margin-top'}->{parse},
1595      #allow_negative => 0,
1596      keyword => {none => 1},
1597      serialize => $default_serializer,
1598      initial => ['KEYWORD', 'none'],
1599      #inherited => 0,
1600      compute => $compute_length,
1601    };
1602    $Attr->{max_width} = $Prop->{'max-width'};
1603    $Key->{max_width} = $Prop->{'max-width'};
1604    
1605    $Prop->{height} = {
1606      css => 'height',
1607      dom => 'height',
1608      key => 'height',
1609      parse => $Prop->{'margin-top'}->{parse},
1610      #allow_negative => 0,
1611      keyword => {auto => 1},
1612      serialize => $default_serializer,
1613      initial => ['KEYWORD', 'auto'],
1614      #inherited => 0,
1615      compute => $compute_length,
1616          ## NOTE: See <http://suika.fam.cx/gate/2005/sw/height> for
1617          ## browser compatibility issues.
1618    };
1619    $Attr->{height} = $Prop->{height};
1620    $Key->{height} = $Prop->{height};
1621    
1622    $Prop->{'min-height'} = {
1623      css => 'min-height',
1624      dom => 'min_height',
1625      key => 'min_height',
1626      parse => $Prop->{'margin-top'}->{parse},
1627      #allow_negative => 0,
1628      #keyword => {},
1629      serialize => $default_serializer,
1630      initial => ['DIMENSION', 0, 'px'],
1631      #inherited => 0,
1632      compute => $compute_length,
1633    };
1634    $Attr->{min_height} = $Prop->{'min-height'};
1635    $Key->{min_height} = $Prop->{'min-height'};
1636    
1637    $Prop->{'max-height'} = {
1638      css => 'max-height',
1639      dom => 'max_height',
1640      key => 'max_height',
1641      parse => $Prop->{'margin-top'}->{parse},
1642      #allow_negative => 0,
1643      keyword => {none => 1},
1644      serialize => $default_serializer,
1645      initial => ['KEYWORD', 'none'],
1646      #inherited => 0,
1647      compute => $compute_length,
1648    };
1649    $Attr->{max_height} = $Prop->{'max-height'};
1650    $Key->{max_height} = $Prop->{'max-height'};
1651    
1652    $Prop->{'line-height'} = {
1653      css => 'line-height',
1654      dom => 'line_height',
1655      key => 'line_height',
1656    parse => sub {    parse => sub {
1657      my ($self, $prop_name, $tt, $t, $onerror) = @_;      my ($self, $prop_name, $tt, $t, $onerror) = @_;
1658    
1659        ## NOTE: Similar to 'margin-top', but different handling
1660        ## for unitless numbers.
1661    
1662      my $sign = 1;      my $sign = 1;
1663      if ($t->{type} == MINUS_TOKEN) {      if ($t->{type} == MINUS_TOKEN) {
1664        $t = $tt->get_next_token;        $t = $tt->get_next_token;
1665        $sign = -1;        $sign = -1;
1666      }      }
1667        my $allow_negative = $Prop->{$prop_name}->{allow_negative};
1668    
1669      if ($t->{type} == DIMENSION_TOKEN) {      if ($t->{type} == DIMENSION_TOKEN) {
1670        my $value = $t->{number} * $sign;        my $value = $t->{number} * $sign;
# Line 1556  $Prop->{'padding-top'} = { Line 1676  $Prop->{'padding-top'} = {
1676      } elsif ($t->{type} == PERCENTAGE_TOKEN) {      } elsif ($t->{type} == PERCENTAGE_TOKEN) {
1677        my $value = $t->{number} * $sign;        my $value = $t->{number} * $sign;
1678        $t = $tt->get_next_token;        $t = $tt->get_next_token;
1679        return ($t, {$prop_name => ['PERCENTAGE', $value]}) if $value >= 0;        return ($t, {$prop_name => ['PERCENTAGE', $value]})
1680      } elsif ($t->{type} == NUMBER_TOKEN and            if $value >= 0;
1681               ($self->{unitless_px} or $t->{number} == 0)) {      } elsif ($t->{type} == NUMBER_TOKEN) {
1682        my $value = $t->{number} * $sign;        my $value = $t->{number} * $sign;
1683        $t = $tt->get_next_token;        $t = $tt->get_next_token;
1684        return ($t, {$prop_name => ['DIMENSION', $value, 'px']}) if $value >= 0;        return ($t, {$prop_name => ['NUMBER', $value]}) if $value >= 0;
1685      } elsif ($sign > 0 and $t->{type} == IDENT_TOKEN) {      } elsif ($sign > 0 and $t->{type} == IDENT_TOKEN) {
1686        my $value = lc $t->{value}; ## TODO: case        my $value = lc $t->{value}; ## TODO: case
1687        $t = $tt->get_next_token;        $t = $tt->get_next_token;
1688        if ($value eq 'inherit') {        if ($value eq 'normal') {
1689            return ($t, {$prop_name => ['KEYWORD', $value]});        
1690          } elsif ($value eq 'inherit') {
1691          return ($t, {$prop_name => ['INHERIT']});          return ($t, {$prop_name => ['INHERIT']});
1692        }        }
1693      }      }
# Line 1576  $Prop->{'padding-top'} = { Line 1698  $Prop->{'padding-top'} = {
1698      return ($t, undef);      return ($t, undef);
1699    },    },
1700    serialize => $default_serializer,    serialize => $default_serializer,
1701      initial => ['KEYWORD', 'normal'],
1702      inherited => 1,
1703      compute => $compute_length,
1704    };
1705    $Attr->{line_height} = $Prop->{'line-height'};
1706    $Key->{line_height} = $Prop->{'line-height'};
1707    
1708    $Prop->{'vertical-align'} = {
1709      css => 'vertical-align',
1710      dom => 'vertical_align',
1711      key => 'vertical_align',
1712      parse => $Prop->{'margin-top'}->{parse},
1713      allow_negative => 1,
1714      keyword => {
1715        baseline => 1, sub => 1, super => 1, top => 1, 'text-top' => 1,
1716        middle => 1, bottom => 1, 'text-bottom' => 1,
1717      },
1718      ## NOTE: Currently, we don't support option to select subset of keywords
1719      ## supported by application (i.e.
1720      ## $parser->{prop_value}->{'line-height'->{$keyword}).  Should we support
1721      ## it?
1722      serialize => $default_serializer,
1723      initial => ['KEYWORD', 'baseline'],
1724      #inherited => 0,
1725      compute => $compute_length,
1726          ## NOTE: See <http://suika.fam.cx/gate/2005/sw/vertical-align> for
1727          ## browser compatibility issues.
1728    };
1729    $Attr->{vertical_align} = $Prop->{'vertical-align'};
1730    $Key->{vertical_align} = $Prop->{'vertical-align'};
1731    
1732    $Prop->{'padding-top'} = {
1733      css => 'padding-top',
1734      dom => 'padding_top',
1735      key => 'padding_top',
1736      parse => $Prop->{'margin-top'}->{parse},
1737      #allow_negative => 0,
1738      #keyword => {},
1739      serialize => $default_serializer,
1740    initial => ['DIMENSION', 0, 'px'],    initial => ['DIMENSION', 0, 'px'],
1741    #inherited => 0,    #inherited => 0,
1742    compute => $compute_length,    compute => $compute_length,
# Line 1588  $Prop->{'padding-bottom'} = { Line 1749  $Prop->{'padding-bottom'} = {
1749    dom => 'padding_bottom',    dom => 'padding_bottom',
1750    key => 'padding_bottom',    key => 'padding_bottom',
1751    parse => $Prop->{'padding-top'}->{parse},    parse => $Prop->{'padding-top'}->{parse},
1752      #allow_negative => 0,
1753      #keyword => {},
1754    serialize => $default_serializer,    serialize => $default_serializer,
1755    initial => ['DIMENSION', 0, 'px'],    initial => ['DIMENSION', 0, 'px'],
1756    #inherited => 0,    #inherited => 0,
# Line 1601  $Prop->{'padding-right'} = { Line 1764  $Prop->{'padding-right'} = {
1764    dom => 'padding_right',    dom => 'padding_right',
1765    key => 'padding_right',    key => 'padding_right',
1766    parse => $Prop->{'padding-top'}->{parse},    parse => $Prop->{'padding-top'}->{parse},
1767      #allow_negative => 0,
1768      #keyword => {},
1769    serialize => $default_serializer,    serialize => $default_serializer,
1770    initial => ['DIMENSION', 0, 'px'],    initial => ['DIMENSION', 0, 'px'],
1771    #inherited => 0,    #inherited => 0,
# Line 1614  $Prop->{'padding-left'} = { Line 1779  $Prop->{'padding-left'} = {
1779    dom => 'padding_left',    dom => 'padding_left',
1780    key => 'padding_left',    key => 'padding_left',
1781    parse => $Prop->{'padding-top'}->{parse},    parse => $Prop->{'padding-top'}->{parse},
1782      #allow_negative => 0,
1783      #keyword => {},
1784    serialize => $default_serializer,    serialize => $default_serializer,
1785    initial => ['DIMENSION', 0, 'px'],    initial => ['DIMENSION', 0, 'px'],
1786    #inherited => 0,    #inherited => 0,
# Line 1626  $Prop->{'border-top-width'} = { Line 1793  $Prop->{'border-top-width'} = {
1793    css => 'border-top-width',    css => 'border-top-width',
1794    dom => 'border_top_width',    dom => 'border_top_width',
1795    key => 'border_top_width',    key => 'border_top_width',
1796    parse => sub {    parse => $Prop->{'margin-top'}->{parse},
1797      my ($self, $prop_name, $tt, $t, $onerror) = @_;    #allow_negative => 0,
1798      keyword => {thin => 1, medium => 1, thick => 1},
     my $sign = 1;  
     if ($t->{type} == MINUS_TOKEN) {  
       $t = $tt->get_next_token;  
       $sign = -1;  
     }  
   
     if ($t->{type} == DIMENSION_TOKEN) {  
       my $value = $t->{number} * $sign;  
       my $unit = lc $t->{value}; ## TODO: case  
       $t = $tt->get_next_token;  
       if ($length_unit->{$unit} and $value >= 0) {  
         return ($t, {$prop_name => ['DIMENSION', $value, $unit]});  
       }  
     } elsif ($t->{type} == NUMBER_TOKEN and  
              ($self->{unitless_px} or $t->{number} == 0)) {  
       my $value = $t->{number} * $sign;  
       $t = $tt->get_next_token;  
       return ($t, {$prop_name => ['DIMENSION', $value, 'px']}) if $value >= 0;  
     } elsif ($sign > 0 and $t->{type} == IDENT_TOKEN) {  
       my $value = lc $t->{value}; ## TODO: case  
       $t = $tt->get_next_token;  
       if ({thin => 1, medium => 1, thick => 1}->{$value}) {  
         return ($t, {$prop_name => ['KEYWORD', $value]});  
       } elsif ($value eq 'inherit') {  
         return ($t, {$prop_name => ['INHERIT']});  
       }  
     }  
       
     $onerror->(type => 'syntax error:'.$prop_name,  
                level => $self->{must_level},  
                token => $t);  
     return ($t, undef);  
   },  
1799    serialize => $default_serializer,    serialize => $default_serializer,
1800    initial => ['KEYWORD', 'medium'],    initial => ['KEYWORD', 'medium'],
1801    #inherited => 0,    #inherited => 0,
# Line 1697  $Prop->{'border-right-width'} = { Line 1831  $Prop->{'border-right-width'} = {
1831    dom => 'border_right_width',    dom => 'border_right_width',
1832    key => 'border_right_width',    key => 'border_right_width',
1833    parse => $Prop->{'border-top-width'}->{parse},    parse => $Prop->{'border-top-width'}->{parse},
1834      #allow_negative => 0,
1835      keyword => {thin => 1, medium => 1, thick => 1},
1836    serialize => $default_serializer,    serialize => $default_serializer,
1837    initial => ['KEYWORD', 'medium'],    initial => ['KEYWORD', 'medium'],
1838    #inherited => 0,    #inherited => 0,
# Line 1710  $Prop->{'border-bottom-width'} = { Line 1846  $Prop->{'border-bottom-width'} = {
1846    dom => 'border_bottom_width',    dom => 'border_bottom_width',
1847    key => 'border_bottom_width',    key => 'border_bottom_width',
1848    parse => $Prop->{'border-top-width'}->{parse},    parse => $Prop->{'border-top-width'}->{parse},
1849      #allow_negative => 0,
1850      keyword => {thin => 1, medium => 1, thick => 1},
1851    serialize => $default_serializer,    serialize => $default_serializer,
1852    initial => ['KEYWORD', 'medium'],    initial => ['KEYWORD', 'medium'],
1853    #inherited => 0,    #inherited => 0,
# Line 1723  $Prop->{'border-left-width'} = { Line 1861  $Prop->{'border-left-width'} = {
1861    dom => 'border_left_width',    dom => 'border_left_width',
1862    key => 'border_left_width',    key => 'border_left_width',
1863    parse => $Prop->{'border-top-width'}->{parse},    parse => $Prop->{'border-top-width'}->{parse},
1864      #allow_negative => 0,
1865      keyword => {thin => 1, medium => 1, thick => 1},
1866    serialize => $default_serializer,    serialize => $default_serializer,
1867    initial => ['KEYWORD', 'medium'],    initial => ['KEYWORD', 'medium'],
1868    #inherited => 0,    #inherited => 0,

Legend:
Removed from v.1.21  
changed lines
  Added in v.1.22

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24