public void LinesShouldBeCorrectlyCalculated() { //string content = "// ===================================================================================================================================================\r\n// The philosophy and measurements come from the section \"A proposed overhaul\" in FogBugz 9788, further details may be found in the four comments\r\n// following it: \"iPhone 3 and low-dpi tablets\", \"Desktop\", \"Modern Mobile\" and \"Mid-or-hi-dpi Tablet\"\r\n// - There is no overlap between targets such as \"desktop\" and \"phoneHiDpi\" so it should always be clear which target any given device in any\r\n// given configuration (eg. landscape orientation) will have applied. The same approach is applied to the basic pixel break points; no\r\n// overlaps.\r\n// ===================================================================================================================================================\r\n// Configurable values\r\n// ===============================================================================================\r\n// Breakpoint measurements in pixels\r\n@breakPoint320InPixels: 320;\r\n@breakPoint480InPixels: 480;\r\n@breakPoint560InPixels: 560;\r\n@breakPoint760InPixels: 768;\r\n@breakPoint880InPixels: 920;\r\n@breakPoint980InPixels: 994;\r\n@breakPointWideInPixels: 1450;\r\n\r\n// Measurements to differentiate between hardware devices\r\n// - To differentiate between a desktop device and a low-dpi tablet we look at the min/max-device-height when in landscape and min/max-device-width\r\n// when portrait (the logic being that a 10\" tablet may be 211mm high when in landscape but 338mm high when in portrait, which is higher than\r\n// most monitors, so we can't differentiate on device-height only). Using min/max-device-width/height means that desktops are not categorised\r\n// as tablets if the browser window is made too small vertically (which using min/max-width would).\r\n// - 2013-12-17 DWR: We now need different landscape and portrait desktop min device heights since we've had to sacrifice the low-dpi tablet 10\"\r\n// landscape breakpoint since there was no way to differentiate between it and a small laptop screen (10\" tablet was 211mm high in landscape\r\n// but a laptop used for comparison was 203mm). In order to keep the low-dpi 10\" tablet displaying as a tablet in portrait, \r\n// - 2014-03-12 DG: The reference to tenInchTabletMinLandscapeWidthInMM has been changed from 290 to 270 to incorporate the Ipad Air, as this was not picking up\r\n// elements such as the Mega Nav at Landscape Level\r\n@tabletMinLandscapeWidthInMM: 210;\r\n@tabletMinPortraitWidthInMM: 159;\r\n@tenInchTabletMinLandscapeWidthInMM: 270;\r\n@desktopMonitorMinLandscapeDeviceHeightInMM: 200;\r\n@desktopMonitorMinPortraitDeviceHeightInMM: 220;\r\n\r\n// ===============================================================================================\r\n// These are all calculated and shouldn't have to be changed (unless new breakpoints are added)\r\n// ===============================================================================================\r\n// - General breakpoint cutoffs\r\n@breakPoint320AfterInPixels: @breakPoint320InPixels + 1;\r\n@breakPoint480AfterInPixels: @breakPoint480InPixels + 1;\r\n@breakPoint560AfterInPixels: @breakPoint560InPixels + 1;\r\n@breakPoint760AfterInPixels: @breakPoint760InPixels + 1;\r\n@breakPoint880AfterInPixels: @breakPoint880InPixels + 1;\r\n@breakPoint980AfterInPixels: @breakPoint980InPixels + 1;\r\n@breakPoint320: ~\"@{breakPoint320InPixels}px\";\r\n@breakPoint480: ~\"@{breakPoint480InPixels}px\";\r\n@breakPoint560: ~\"@{breakPoint560InPixels}px\";\r\n@breakPoint760: ~\"@{breakPoint760InPixels}px\";\r\n@breakPoint880: ~\"@{breakPoint880InPixels}px\";\r\n@breakPoint980: ~\"@{breakPoint980InPixels}px\";\r\n@breakPointWide: ~\"@{breakPointWideInPixels}px\";\r\n@breakPoint320After: ~\"@{breakPoint320AfterInPixels}px\";\r\n@breakPoint480After: ~\"@{breakPoint480AfterInPixels}px\";\r\n@breakPoint560After: ~\"@{breakPoint560AfterInPixels}px\";\r\n@breakPoint760After: ~\"@{breakPoint760AfterInPixels}px\";\r\n@breakPoint880After: ~\"@{breakPoint880AfterInPixels}px\";\r\n@breakPoint980After: ~\"@{breakPoint980AfterInPixels}px\";\r\n\r\n// - Tablet physical size start point (to differentiate between phones and tablets, required for hi-dpi devices only)\r\n@tabletMinLandscapeWidth: ~\"@{tabletMinLandscapeWidthInMM}mm\";\r\n@tabletMinLandscapeWidthBeforeInMM: @tabletMinLandscapeWidthInMM - 1;\r\n@tabletMinLandscapeWidthBefore: ~\"@{tabletMinLandscapeWidthBeforeInMM}mm\";\r\n@tabletMinPortraitWidth: ~\"@{tabletMinPortraitWidthInMM}mm\";\r\n@tabletMinPortraitWidthBeforeInMM: @tabletMinPortraitWidthInMM - 1;\r\n@tabletMinPortraitWidthBefore: ~\"@{tabletMinPortraitWidthBeforeInMM}mm\";\r\n\r\n// - Tablet physical size differentiations (between 7\" and 10\")\r\n@tenInchTabletMinLandscapeWidth: ~\"@{tenInchTabletMinLandscapeWidthInMM}mm\";\r\n@tenInchTabletMinLandscapeWidthBeforeInMM: @tenInchTabletMinLandscapeWidthInMM - 1;\r\n@tenInchTabletMinLandscapeWidthBefore: ~\"@{tenInchTabletMinLandscapeWidthBeforeInMM}mm\";\r\n\r\n// - Desktop physical size differentiations (between tablets and desktops, required for low-dpi devices only)\r\n@desktopMonitorMinLandscapeDeviceHeight: ~\"@{desktopMonitorMinLandscapeDeviceHeightInMM}mm\";\r\n@desktopMonitorMinLandscapeDeviceHeightBeforeInMM: @desktopMonitorMinLandscapeDeviceHeightInMM - 1;\r\n@desktopMonitorMinLandscapeDeviceHeightBefore: ~\"@{desktopMonitorMinLandscapeDeviceHeightBeforeInMM}mm\";\r\n@desktopMonitorMinPortraitDeviceHeight: ~\"@{desktopMonitorMinPortraitDeviceHeightInMM}mm\";\r\n@desktopMonitorMinPortraitDeviceHeightBeforeInMM: @desktopMonitorMinPortraitDeviceHeightInMM - 1;\r\n@desktopMonitorMinPortraitDeviceHeightBefore: ~\"@{desktopMonitorMinPortraitDeviceHeightBeforeInMM}mm\";\r\n\r\n// ===============================================================================================\r\n// Breakpoint categories\r\n// ===============================================================================================\r\n@desktopStandardsLandscape: ~\"all and (max-resolution: 229dpi) and (orientation: landscape) and (min-device-height: @{desktopMonitorMinLandscapeDeviceHeight})\";\r\n@desktopStandardsPortrait: ~\"all and (max-resolution: 229dpi) and (orientation: portrait) and (min-device-width: @{desktopMonitorMinPortraitDeviceHeight})\";\r\n@desktopWebKitLandscape: ~\"all and (-webkit-max-device-pixel-ratio: 23.395) and (orientation: landscape) and (min-device-height: @{desktopMonitorMinLandscapeDeviceHeight})\";\r\n@desktopWebKitPortrait: ~\"all and (-webkit-max-device-pixel-ratio: 23.395) and (orientation: portrait) and (min-device-width: @{desktopMonitorMinPortraitDeviceHeight})\";\r\n\r\n@phoneTabletLowDpiStandardsLandscape: ~\"all and (max-resolution: 229dpi) and (orientation: landscape) and (max-device-height: @{desktopMonitorMinLandscapeDeviceHeightBefore})\";\r\n@phoneTabletLowDpiStandardsPortrait: ~\"all and (max-resolution: 229dpi) and (orientation: portrait) and (max-device-width: @{desktopMonitorMinPortraitDeviceHeightBefore})\";\r\n@phoneTabletLowDpiWebKitLandscape: ~\"all and (-webkit-max-device-pixel-ratio: 23.395) and (orientation: landscape) and (max-device-height: @{desktopMonitorMinLandscapeDeviceHeightBefore})\";\r\n@phoneTabletLowDpiWebKitPortrait: ~\"all and (-webkit-max-device-pixel-ratio: 23.395) and (orientation: portrait) and (max-device-width: @{desktopMonitorMinPortraitDeviceHeightBefore})\";\r\n\r\n@phoneHiDpiStandardsLandscape: ~\"all and (min-resolution: 230dpi) and (orientation: landscape) and (max-width: @{tabletMinLandscapeWidthBefore})\";\r\n@phoneHiDpiStandardsPortrait: ~\"all and (min-resolution: 230dpi) and (orientation: portrait) and (max-width: @{tabletMinPortraitWidthBefore})\";\r\n@phoneHiDpiWebKitLandscape: ~\"all and (-webkit-min-device-pixel-ratio: 23.396) and (orientation: landscape) and (max-width: @{tabletMinLandscapeWidthBefore})\";\r\n@phoneHiDpiWebKitPortrait: ~\"all and (-webkit-min-device-pixel-ratio: 23.396) and (orientation: portrait) and (max-width: @{tabletMinPortraitWidthBefore})\";\r\n\r\n@tabletHiDpiStandardsLandscape: ~\"all and (min-resolution: 230dpi) and (orientation: landscape) and (min-width: @{tabletMinLandscapeWidth})\";\r\n@tabletHiDpiStandardsPortrait: ~\"all and (min-resolution: 230dpi) and (orientation: portrait) and (min-width: @{tabletMinPortraitWidth})\";\r\n@tabletHiDpiWebKitLandscape: ~\"all and (-webkit-min-device-pixel-ratio: 23.396) and (orientation: landscape) and (min-width: @{tabletMinLandscapeWidth})\";\r\n@tabletHiDpiWebKitPortrait: ~\"all and (-webkit-min-device-pixel-ratio: 23.396) and (orientation: portrait) and (min-width: @{tabletMinPortraitWidth})\";\r\n\r\n// ===============================================================================================\r\n// Base media query bands\r\n// - There should be no overlap between bands for any device / orientation\r\n// - If any changes are made here, ensure that they are propogated through the \"Extended/ranged\r\n// media query bands\" content further down\r\n// ===============================================================================================\r\n// \"Narrow Mobile\"\r\n// Only expect this to hit vary narrow desktop browsers (for demonstration purposes) and mobiles which report very low widths (eg iPhone 3G's\r\n// genuine width and iPhone 4s reported width)\r\n@ResponsiveTo320:\r\n ~\"@{desktopStandardsLandscape} and (max-width: @{breakPoint320}),\"\r\n ~\"@{desktopStandardsPortrait} and (max-width: @{breakPoint320}),\"\r\n ~\"@{desktopWebKitLandscape} and (max-width: @{breakPoint320}),\"\r\n ~\"@{desktopWebKitPortrait} and (max-width: @{breakPoint320}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (max-width: @{breakPoint320}),\"\r\n ~\"@{phoneTabletLowDpiStandardsPortrait} and (max-width: @{breakPoint320}),\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (max-width: @{breakPoint320}),\"\r\n ~\"@{phoneTabletLowDpiWebKitPortrait} and (max-width: @{breakPoint320}),\"\r\n ~\"@{phoneHiDpiStandardsLandscape} and (max-width: @{breakPoint320}),\"\r\n ~\"@{phoneHiDpiStandardsPortrait} and (max-width: @{breakPoint320}),\"\r\n ~\"@{phoneHiDpiWebKitLandscape} and (max-width: @{breakPoint320}),\"\r\n ~\"@{phoneHiDpiWebKitPortrait} and (max-width: @{breakPoint320})\";\r\n\r\n// \"Mobile\"\r\n// Note that HiDpi phones are capped at this breakpoint (there is no max-width for them here)\r\n@Responsive320To480:\r\n ~\"@{desktopStandardsLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint480}),\"\r\n ~\"@{desktopStandardsPortrait} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint480}),\"\r\n ~\"@{desktopWebKitLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint480}),\"\r\n ~\"@{desktopWebKitPortrait} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneTabletLowDpiStandardsPortrait} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneTabletLowDpiWebKitPortrait} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneHiDpiStandardsLandscape} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiStandardsPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiWebKitLandscape} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiWebKitPortrait} and (min-width: @{breakPoint320After})\";\r\n\r\n// \"Desktop mid-way convenience point only\"\r\n// Note: This is a mid-way breakpoint that is only really intended for desktop devices. As such, we only consider the desktop devices here.\r\n@Responsive480To560:\r\n ~\"@{desktopStandardsLandscape} and (min-width: @{breakPoint480After}) and (max-width: @{breakPoint560}),\"\r\n ~\"@{desktopStandardsPortrait} and (min-width: @{breakPoint480After}) and (max-width: @{breakPoint560}),\"\r\n ~\"@{desktopWebKitLandscape} and (min-width: @{breakPoint480After}) and (max-width: @{breakPoint560}),\"\r\n ~\"@{desktopWebKitPortrait} and (min-width: @{breakPoint480After}) and (max-width: @{breakPoint560})\";\r\n\r\n// \"Tablet Portrait\"\r\n// Note that HiDpi tablets are only introduced here since they may only be in this breakpoint (if portrait, regardless of size) or \"Small\r\n// Tablet Landscape\" (if less than 10\" landscape) or \"Big Tablet Landscape (if 10\" or greater landscape). The table portrait restriction\r\n// means that tablets in portrait are capped here (no max-width). Also note that the min-width values for the tablets and phones are 480\r\n// and not 560, this is because the 560 breakpoint above is not applied to tablets or phones and so, to them, it is as if the 560\r\n// breakpoint does not exist.\r\n@Responsive560To760:\r\n ~\"@{desktopStandardsLandscape} and (min-width: @{breakPoint560After}) and (max-width: @{breakPoint760}),\"\r\n ~\"@{desktopStandardsPortrait} and (min-width: @{breakPoint560After}) and (max-width: @{breakPoint760}),\"\r\n ~\"@{desktopWebKitLandscape} and (min-width: @{breakPoint560After}) and (max-width: @{breakPoint760}),\"\r\n ~\"@{desktopWebKitPortrait} and (min-width: @{breakPoint560After}) and (max-width: @{breakPoint760}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (min-width: @{breakPoint480After}) and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{phoneTabletLowDpiStandardsPortrait} and (min-width: @{breakPoint480After}),\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (min-width: @{breakPoint480After}) and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{phoneTabletLowDpiWebKitPortrait} and (min-width: @{breakPoint480After}),\"\r\n ~\"@{tabletHiDpiStandardsPortrait},\"\r\n ~\"@{tabletHiDpiWebKitPortrait}\";\r\n\r\n// \"Small Tablet Landscape / Desktop FatButton NonMegaNav\"\r\n// Historically, this was only ever used as a mid-way breakpoint for desktops (like \"Responsive480To560\") but recently (as of 2014-03-12) it\r\n// has been decided to use the full MegaNav for large tablets in landscape but the menu button for smaller tablets in landscape, so now this\r\n// breakpoint is used to make that distinction.\r\n@Responsive760To880:\r\n ~\"@{desktopStandardsLandscape} and (min-width: @{breakPoint760After}) and (max-width: @{breakPoint880}),\"\r\n ~\"@{desktopStandardsPortrait} and (min-width: @{breakPoint760After}) and (max-width: @{breakPoint880}),\"\r\n ~\"@{desktopWebKitLandscape} and (min-width: @{breakPoint760After}) and (max-width: @{breakPoint880}),\"\r\n ~\"@{desktopWebKitPortrait} and (min-width: @{breakPoint760After}) and (max-width: @{breakPoint880}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (min-width: @{breakPoint760After}) and (max-width: @{breakPoint880}),\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (min-width: @{breakPoint760After}) and (max-width: @{breakPoint880}),\"\r\n ~\"@{tabletHiDpiStandardsLandscape} and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{tabletHiDpiWebKitLandscape} and (max-width: @{tenInchTabletMinLandscapeWidthBefore})\";\r\n\r\n// \"Big Tablet Landscape / Desktop FatButton\"\r\n// Note that tablets are capped at this breakpoint (there is no max-width for them here) and portrait tablet are not here at all as they\r\n// will never hit this breakpoint in portrait.\r\n@Responsive880To980:\r\n ~\"@{desktopStandardsLandscape} and (min-width: @{breakPoint880After}) and (max-width: @{breakPoint980}),\"\r\n ~\"@{desktopStandardsPortrait} and (min-width: @{breakPoint880After}) and (max-width: @{breakPoint980}),\"\r\n ~\"@{desktopWebKitLandscape} and (min-width: @{breakPoint880After}) and (max-width: @{breakPoint980}),\"\r\n ~\"@{desktopWebKitPortrait} and (min-width: @{breakPoint880After}) and (max-width: @{breakPoint980}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (min-width: @{breakPoint880After}) and (max-width: @{breakPoint980}),\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (min-width: @{breakPoint880After}) and (max-width: @{breakPoint980}),\"\r\n ~\"@{tabletHiDpiStandardsLandscape} and (min-width: @{tenInchTabletMinLandscapeWidth}),\"\r\n ~\"@{tabletHiDpiWebKitLandscape} and (min-width: @{tenInchTabletMinLandscapeWidth})\";\r\n\r\n// 2014-01-23 DWR: There is no mention of the \"wide\" breakpoint here, that exists only as a \"ResponsiveWide\" value. The logic being that\r\n// we are introducing a guideline that the \"default site appearance\" should never be targetted by media queries so that legacy browsers\r\n// (IE7 and 8) which do not support media queries always see the default site. If there were ranges such as \"ResponsiveToWide\" or\r\n// \"Responsive480ToWide\" then there would be media queries affecting the default site layout, which is not allowed.\r\n\r\n// ===============================================================================================\r\n// Extended/ranged media query bands\r\n// - These are combinations of the above criteria (eg. instead of ResponsiveTo320 and\r\n// Responsive320To480, it may be useful to target ResponsiveTo480)\r\n// - These should be taken by combining criteria from above, ensure that any changes made there\r\n// are always reflected here\r\n// ===============================================================================================\r\n// Extended/ranged media query bands: From 0px\r\n// ===============================================================================================\r\n// Note that these ranged brackets (that effectively start from 0px and go up to at least 480px) will always contain HiDpi phones, regardless\r\n// of resolution or orientation since they may only ever go into the 320 or 480 breakpoints and these brackets covers both of thoses\r\n@ResponsiveTo480:\r\n ~\"@{desktopStandardsLandscape} and (max-width: @{breakPoint480}),\"\r\n ~\"@{desktopStandardsPortrait} and (max-width: @{breakPoint480}),\"\r\n ~\"@{desktopWebKitLandscape} and (max-width: @{breakPoint480}),\"\r\n ~\"@{desktopWebKitPortrait} and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneTabletLowDpiStandardsPortrait} and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneTabletLowDpiWebKitPortrait} and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneHiDpiStandardsLandscape},\"\r\n ~\"@{phoneHiDpiStandardsPortrait},\"\r\n ~\"@{phoneHiDpiWebKitLandscape},\"\r\n ~\"@{phoneHiDpiWebKitPortrait}\";\r\n\r\n// The 560 breakpoint only applies to desktop targets, so the LowDpi phone/tablet targets only go up to @breakPoint480 here\r\n@ResponsiveTo560:\r\n ~\"@{desktopStandardsLandscape} and (max-width: @{breakPoint560}),\"\r\n ~\"@{desktopStandardsPortrait} and (max-width: @{breakPoint560}),\"\r\n ~\"@{desktopWebKitLandscape} and (max-width: @{breakPoint560}),\"\r\n ~\"@{desktopWebKitPortrait} and (max-width: @{breakPoint560}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneTabletLowDpiStandardsPortrait} and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneTabletLowDpiWebKitPortrait} and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneHiDpiStandardsLandscape},\"\r\n ~\"@{phoneHiDpiStandardsPortrait},\"\r\n ~\"@{phoneHiDpiWebKitLandscape},\"\r\n ~\"@{phoneHiDpiWebKitPortrait}\";\r\n\r\n@ResponsiveTo760:\r\n ~\"@{desktopStandardsLandscape} and (max-width: @{breakPoint760}),\"\r\n ~\"@{desktopStandardsPortrait} and (max-width: @{breakPoint760}),\"\r\n ~\"@{desktopWebKitLandscape} and (max-width: @{breakPoint760}),\"\r\n ~\"@{desktopWebKitPortrait} and (max-width: @{breakPoint760}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{phoneTabletLowDpiStandardsPortrait},\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{phoneTabletLowDpiWebKitPortrait},\"\r\n ~\"@{tabletHiDpiStandardsPortrait},\"\r\n ~\"@{tabletHiDpiWebKitPortrait},\"\r\n ~\"@{phoneHiDpiStandardsLandscape},\"\r\n ~\"@{phoneHiDpiStandardsPortrait},\"\r\n ~\"@{phoneHiDpiWebKitLandscape},\"\r\n ~\"@{phoneHiDpiWebKitPortrait}\";\r\n\r\n@ResponsiveTo880:\r\n ~\"@{desktopStandardsLandscape} and (max-width: @{breakPoint880}),\"\r\n ~\"@{desktopStandardsPortrait} and (max-width: @{breakPoint880}),\"\r\n ~\"@{desktopWebKitLandscape} and (max-width: @{breakPoint880}),\"\r\n ~\"@{desktopWebKitPortrait} and (max-width: @{breakPoint880}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{phoneTabletLowDpiStandardsPortrait},\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{phoneTabletLowDpiWebKitPortrait},\"\r\n ~\"@{tabletHiDpiStandardsLandscape} and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{tabletHiDpiWebKitLandscape} and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{tabletHiDpiStandardsPortrait},\"\r\n ~\"@{tabletHiDpiWebKitPortrait},\"\r\n ~\"@{phoneHiDpiStandardsLandscape},\"\r\n ~\"@{phoneHiDpiStandardsPortrait},\"\r\n ~\"@{phoneHiDpiWebKitLandscape},\"\r\n ~\"@{phoneHiDpiWebKitPortrait}\";\r\n\r\n// The only device that needs a width cap is the desktop; all others (phones and tablets - regardless of resolution, orientation or\r\n// dpi) will be within this range that goes all the way from 0px (effectively) to 980px\r\n@ResponsiveTo980:\r\n ~\"@{desktopStandardsLandscape} and (max-width: @{breakPoint980}),\"\r\n ~\"@{desktopStandardsPortrait} and (max-width: @{breakPoint980}),\"\r\n ~\"@{desktopWebKitLandscape} and (max-width: @{breakPoint980}),\"\r\n ~\"@{desktopWebKitPortrait} and (max-width: @{breakPoint980}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape},\"\r\n ~\"@{phoneTabletLowDpiStandardsPortrait},\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape},\"\r\n ~\"@{phoneTabletLowDpiWebKitPortrait},\"\r\n ~\"@{tabletHiDpiStandardsLandscape},\"\r\n ~\"@{tabletHiDpiStandardsPortrait},\"\r\n ~\"@{tabletHiDpiWebKitLandscape},\"\r\n ~\"@{tabletHiDpiWebKitPortrait},\"\r\n ~\"@{phoneHiDpiStandardsLandscape},\"\r\n ~\"@{phoneHiDpiStandardsPortrait},\"\r\n ~\"@{phoneHiDpiWebKitLandscape},\"\r\n ~\"@{phoneHiDpiWebKitPortrait}\";\r\n\r\n// ===============================================================================================\r\n// Extended/ranged media query bands: From 320px\r\n// ===============================================================================================\r\n@Responsive320To560:\r\n ~\"@{desktopStandardsLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint560}),\"\r\n ~\"@{desktopStandardsPortrait} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint560}),\"\r\n ~\"@{desktopWebKitLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint560}),\"\r\n ~\"@{desktopWebKitPortrait} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint560}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneTabletLowDpiStandardsPortrait} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneTabletLowDpiWebKitPortrait} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneHiDpiStandardsLandscape} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiStandardsPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiWebKitLandscape} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiWebKitPortrait} and (min-width: @{breakPoint320After})\";\r\n\r\n@Responsive320To760:\r\n ~\"@{desktopStandardsLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint760}),\"\r\n ~\"@{desktopStandardsPortrait} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint760}),\"\r\n ~\"@{desktopWebKitLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint760}),\"\r\n ~\"@{desktopWebKitPortrait} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint760}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneTabletLowDpiStandardsPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneTabletLowDpiWebKitPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiStandardsPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiWebKitLandscape} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiWebKitPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{tabletHiDpiStandardsPortrait},\"\r\n ~\"@{tabletHiDpiWebKitPortrait}\";\r\n\r\n@Responsive320To880:\r\n ~\"@{desktopStandardsLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint880}),\"\r\n ~\"@{desktopStandardsPortrait} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint880}),\"\r\n ~\"@{desktopWebKitLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint880}),\"\r\n ~\"@{desktopWebKitPortrait} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint880}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneTabletLowDpiStandardsPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{phoneTabletLowDpiWebKitPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiStandardsLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{phoneHiDpiStandardsPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiWebKitLandscape} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiWebKitPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{tabletHiDpiStandardsLandscape} and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{tabletHiDpiWebKitLandscape} and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{tabletHiDpiStandardsPortrait},\"\r\n ~\"@{tabletHiDpiWebKitPortrait}\";\r\n\r\n@Responsive320To980:\r\n ~\"@{desktopStandardsLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint980}),\"\r\n ~\"@{desktopStandardsPortrait} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint980}),\"\r\n ~\"@{desktopWebKitLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint980}),\"\r\n ~\"@{desktopWebKitPortrait} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint980}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneTabletLowDpiStandardsPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneTabletLowDpiWebKitPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiStandardsLandscape} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiStandardsPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiWebKitLandscape} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiWebKitPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{tabletHiDpiStandardsLandscape},\"\r\n ~\"@{tabletHiDpiStandardsPortrait},\"\r\n ~\"@{tabletHiDpiWebKitLandscape},\"\r\n ~\"@{tabletHiDpiWebKitPortrait}\";\r\n\r\n// ===============================================================================================\r\n// Extended/ranged media query bands: From 480px\r\n// ===============================================================================================\r\n@Responsive480To760:\r\n ~\"@{desktopStandardsLandscape} and (min-width: @{breakPoint480After}) and (max-width: @{breakPoint760}),\"\r\n ~\"@{desktopStandardsPortrait} and (min-width: @{breakPoint480After}) and (max-width: @{breakPoint760}),\"\r\n ~\"@{desktopWebKitLandscape} and (min-width: @{breakPoint480After}) and (max-width: @{breakPoint760}),\"\r\n ~\"@{desktopWebKitPortrait} and (min-width: @{breakPoint480After}) and (max-width: @{breakPoint760}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (min-width: @{breakPoint480After}) and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneTabletLowDpiStandardsPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{phoneTabletLowDpiWebKitPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiStandardsLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{phoneHiDpiStandardsPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiWebKitLandscape} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiWebKitPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{tabletHiDpiStandardsPortrait},\"\r\n ~\"@{tabletHiDpiWebKitPortrait}\";\r\n\r\n@Responsive480To880:\r\n ~\"@{desktopStandardsLandscape} and (min-width: @{breakPoint480After}) and (max-width: @{breakPoint880}),\"\r\n ~\"@{desktopStandardsPortrait} and (min-width: @{breakPoint480After}) and (max-width: @{breakPoint880}),\"\r\n ~\"@{desktopWebKitLandscape} and (min-width: @{breakPoint480After}) and (max-width: @{breakPoint880}),\"\r\n ~\"@{desktopWebKitPortrait} and (min-width: @{breakPoint480After}) and (max-width: @{breakPoint880}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneTabletLowDpiStandardsPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{phoneTabletLowDpiWebKitPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiStandardsLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{phoneHiDpiStandardsPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiWebKitLandscape} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiWebKitPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{tabletHiDpiStandardsLandscape} and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{tabletHiDpiWebKitLandscape} and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{tabletHiDpiStandardsPortrait},\"\r\n ~\"@{tabletHiDpiWebKitPortrait}\";\r\n\r\n@Responsive480To980:\r\n ~\"@{desktopStandardsLandscape} and (min-width: @{breakPoint480After}) and (max-width: @{breakPoint980}),\"\r\n ~\"@{desktopStandardsPortrait} and (min-width: @{breakPoint480After}) and (max-width: @{breakPoint980}),\"\r\n ~\"@{desktopWebKitLandscape} and (min-width: @{breakPoint480After}) and (max-width: @{breakPoint980}),\"\r\n ~\"@{desktopWebKitPortrait} and (min-width: @{breakPoint480After}) and (max-width: @{breakPoint980}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (min-width: @{breakPoint320After}) and (max-width: @{breakPoint480}),\"\r\n ~\"@{phoneTabletLowDpiStandardsPortrait} and (min-width: @{breakPoint480After}),\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (min-width: @{breakPoint480After}),\"\r\n ~\"@{phoneTabletLowDpiWebKitPortrait} and (min-width: @{breakPoint480After}),\"\r\n ~\"@{phoneHiDpiStandardsLandscape} and (min-width: @{breakPoint480After}),\"\r\n ~\"@{phoneHiDpiStandardsPortrait} and (min-width: @{breakPoint480After}),\"\r\n ~\"@{phoneHiDpiWebKitLandscape} and (min-width: @{breakPoint480After}),\"\r\n ~\"@{phoneHiDpiWebKitPortrait} and (min-width: @{breakPoint480After}),\"\r\n ~\"@{tabletHiDpiStandardsLandscape},\"\r\n ~\"@{tabletHiDpiStandardsPortrait},\"\r\n ~\"@{tabletHiDpiWebKitLandscape},\"\r\n ~\"@{tabletHiDpiWebKitPortrait}\";\r\n\r\n// ===============================================================================================\r\n// Extended/ranged media query bands: From 560px\r\n// ===============================================================================================\r\n@Responsive560To880:\r\n ~\"@{desktopStandardsLandscape} and (min-width: @{breakPoint560After}) and (max-width: @{breakPoint880}),\"\r\n ~\"@{desktopStandardsPortrait} and (min-width: @{breakPoint560After}) and (max-width: @{breakPoint880}),\"\r\n ~\"@{desktopWebKitLandscape} and (min-width: @{breakPoint560After}) and (max-width: @{breakPoint880}),\"\r\n ~\"@{desktopWebKitPortrait} and (min-width: @{breakPoint560After}) and (max-width: @{breakPoint880}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (min-width: @{breakPoint560After}) and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{phoneTabletLowDpiStandardsPortrait} and (min-width: @{breakPoint560After}),\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (min-width: @{breakPoint560After}) and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{phoneTabletLowDpiWebKitPortrait} and (min-width: @{breakPoint560After}),\"\r\n ~\"@{tabletHiDpiStandardsLandscape} and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{tabletHiDpiWebKitLandscape} and (max-width: @{tenInchTabletMinLandscapeWidthBefore}),\"\r\n ~\"@{tabletHiDpiStandardsPortrait},\"\r\n ~\"@{tabletHiDpiWebKitPortrait}\";\r\n\r\n@Responsive560To980:\r\n ~\"@{desktopStandardsLandscape} and (min-width: @{breakPoint560After}) and (max-width: @{breakPoint980}),\"\r\n ~\"@{desktopStandardsPortrait} and (min-width: @{breakPoint560After}) and (max-width: @{breakPoint980}),\"\r\n ~\"@{desktopWebKitLandscape} and (min-width: @{breakPoint560After}) and (max-width: @{breakPoint980}),\"\r\n ~\"@{desktopWebKitPortrait} and (min-width: @{breakPoint560After}) and (max-width: @{breakPoint980}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (min-width: @{breakPoint560After}) and (min-width: @{tenInchTabletMinLandscapeWidth}),\"\r\n ~\"@{phoneTabletLowDpiStandardsPortrait} and (min-width: @{breakPoint560After}),\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (min-width: @{breakPoint560After}) and (min-width: @{tenInchTabletMinLandscapeWidth}),\"\r\n ~\"@{phoneTabletLowDpiWebKitPortrait} and (min-width: @{breakPoint560After}),\"\r\n ~\"@{tabletHiDpiStandardsLandscape},\"\r\n ~\"@{tabletHiDpiStandardsPortrait},\"\r\n ~\"@{tabletHiDpiWebKitLandscape},\"\r\n ~\"@{tabletHiDpiWebKitPortrait}\";\r\n\r\n// ===============================================================================================\r\n// Extended/ranged media query bands: From 760px\r\n// ===============================================================================================\r\n@Responsive760To980:\r\n ~\"@{desktopStandardsLandscape} and (min-width: @{breakPoint760After}) and (max-width: @{breakPoint980}),\"\r\n ~\"@{desktopStandardsPortrait} and (min-width: @{breakPoint760After}) and (max-width: @{breakPoint980}),\"\r\n ~\"@{desktopWebKitLandscape} and (min-width: @{breakPoint760After}) and (max-width: @{breakPoint980}),\"\r\n ~\"@{desktopWebKitPortrait} and (min-width: @{breakPoint760After}) and (max-width: @{breakPoint980}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (min-width: @{breakPoint760After}) and (min-width: @{tenInchTabletMinLandscapeWidth}),\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (min-width: @{breakPoint760After}) and (min-width: @{tenInchTabletMinLandscapeWidth}),\"\r\n ~\"@{tabletHiDpiStandardsLandscape},\"\r\n ~\"@{tabletHiDpiWebKitLandscape}\";\r\n\r\n// ===============================================================================================\r\n// Extended/ranged media query bands: Above\r\n// IMPORTANT: The \"wide\" breakpoint does NOT apply to most of these \"Above\" ranges since that\r\n// would mean that a media query overlaps the \"default\" view, which is a no-no (since styles\r\n// might be applied in it which the default view then relies upon, which will cause problems\r\n// in IE7 and 8 as they don't support media queries)\r\n// ===============================================================================================\r\n// This covers a lot; I started with @Responsive320To980 and then removed any upper limits on width.\r\n// Includes: Mobile, DesktopMidPoint480To560, TabletPortrait, SmallTabletLandscape, LargeTabletLandscape\r\n@ResponsiveAbove320:\r\n ~\"@{desktopStandardsLandscape} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{desktopStandardsPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{desktopWebKitLandscape} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{desktopWebKitPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneTabletLowDpiStandardsPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneTabletLowDpiWebKitPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiStandardsLandscape} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiStandardsPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiWebKitLandscape} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{phoneHiDpiWebKitPortrait} and (min-width: @{breakPoint320After}),\"\r\n ~\"@{tabletHiDpiStandardsLandscape},\"\r\n ~\"@{tabletHiDpiStandardsPortrait},\"\r\n ~\"@{tabletHiDpiWebKitLandscape},\"\r\n ~\"@{tabletHiDpiWebKitPortrait}\";\r\n\r\n// Above 480 counts out HiDpi phones entirely (it also counts out LowDpi phones but they're grouped into the same category as LowDpi tablets).\r\n// I started with @ResponsiveAbove320, bumped up the min-width values and removed the devices that wouldn't be affected.\r\n// Includes: DesktopMidPoint480To560, TabletPortrait, SmallTabletLandscape, LargeTabletLandscape\r\n@ResponsiveAbove480:\r\n ~\"@{desktopStandardsLandscape} and (min-width: @{breakPoint480After}),\"\r\n ~\"@{desktopStandardsPortrait} and (min-width: @{breakPoint480After}),\"\r\n ~\"@{desktopWebKitLandscape} and (min-width: @{breakPoint480After}),\"\r\n ~\"@{desktopWebKitPortrait} and (min-width: @{breakPoint480After}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (min-width: @{breakPoint480After}),\"\r\n ~\"@{phoneTabletLowDpiStandardsPortrait} and (min-width: @{breakPoint480After}),\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (min-width: @{breakPoint480After}),\"\r\n ~\"@{phoneTabletLowDpiWebKitPortrait} and (min-width: @{breakPoint480After}),\"\r\n ~\"@{tabletHiDpiStandardsLandscape},\"\r\n ~\"@{tabletHiDpiStandardsPortrait},\"\r\n ~\"@{tabletHiDpiWebKitLandscape},\"\r\n ~\"@{tabletHiDpiWebKitPortrait}\";\r\n\r\n// Includes: TabletPortrait, SmallTabletLandscape, LargeTabletLandscape\r\n@ResponsiveAbove560:\r\n ~\"@{desktopStandardsLandscape} and (min-width: @{breakPoint560After}),\"\r\n ~\"@{desktopStandardsPortrait} and (min-width: @{breakPoint560After}),\"\r\n ~\"@{desktopWebKitLandscape} and (min-width: @{breakPoint560After}),\"\r\n ~\"@{desktopWebKitPortrait} and (min-width: @{breakPoint560After}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (min-width: @{breakPoint760After}) and (min-width: @{tenInchTabletMinLandscapeWidth}),\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (min-width: @{breakPoint760After}) and (min-width: @{tenInchTabletMinLandscapeWidth}),\"\r\n ~\"@{tabletHiDpiStandardsLandscape},\"\r\n ~\"@{tabletHiDpiStandardsPortrait},\"\r\n ~\"@{tabletHiDpiWebKitLandscape},\"\r\n ~\"@{tabletHiDpiWebKitPortrait}\";\r\n\r\n// Includes: SmallTabletLandscape, LargeTabletLandscape\r\n@ResponsiveAbove760:\r\n ~\"@{desktopStandardsLandscape} and (min-width: @{breakPoint760}),\"\r\n ~\"@{desktopStandardsPortrait} and (min-width: @{breakPoint760}),\"\r\n ~\"@{desktopWebKitLandscape} and (min-width: @{breakPoint760}),\"\r\n ~\"@{desktopWebKitPortrait} and (min-width: @{breakPoint760}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (min-width: @{breakPoint760After}),\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (min-width: @{breakPoint760After}),\"\r\n ~\"@{tabletHiDpiStandardsLandscape},\"\r\n ~\"@{tabletHiDpiWebKitLandscape}\";\r\n\r\n// Includes: LargeTabletLandscape\r\n@ResponsiveAbove880:\r\n ~\"@{desktopStandardsLandscape} and (min-width: @{breakPoint880}),\"\r\n ~\"@{desktopStandardsPortrait} and (min-width: @{breakPoint880}),\"\r\n ~\"@{desktopWebKitLandscape} and (min-width: @{breakPoint880}),\"\r\n ~\"@{desktopWebKitPortrait} and (min-width: @{breakPoint880}),\"\r\n ~\"@{phoneTabletLowDpiStandardsLandscape} and (min-width: @{breakPoint760After}) and (min-width: @{tenInchTabletMinLandscapeWidth}),\"\r\n ~\"@{phoneTabletLowDpiWebKitLandscape} and (min-width: @{breakPoint760After}) and (min-width: @{tenInchTabletMinLandscapeWidth}),\"\r\n ~\"@{tabletHiDpiStandardsLandscape} and (min-width: @{tenInchTabletMinLandscapeWidth}),\"\r\n ~\"@{tabletHiDpiWebKitLandscape} and (min-width: @{tenInchTabletMinLandscapeWidth})\";\r\n\r\n@ResponsiveAbove980:\r\n ~\"@{desktopStandardsLandscape} and (min-width: @{breakPoint980}),\"\r\n ~\"@{desktopStandardsPortrait} and (min-width: @{breakPoint980}),\"\r\n ~\"@{desktopWebKitLandscape} and (min-width: @{breakPoint980}),\"\r\n ~\"@{desktopWebKitPortrait} and (min-width: @{breakPoint980})\";\r\n\r\n// 2014-01-23 DWR: This is the only place that the \"wide\" breakpoint exists since any other media query range would go against the \"no\r\n// media query should affect the default site appearance\" guideline. This is another easy range since it only applies to desktop devices.\r\n@ResponsiveWidestBreak: \r\n ~\"@{desktopStandardsLandscape} and (min-width: @{breakPointWide}),\" \r\n ~\"@{desktopStandardsPortrait} and (min-width: @{breakPointWide}),\"\r\n ~\"@{desktopWebKitLandscape} and (min-width: @{breakPointWide}),\" \r\n ~\"@{desktopWebKitPortrait} and (min-width: @{breakPointWide})\";"; string content = "a:hover { color: blue; }\r\n //silly comment \r\n //in multiple lines\r\n.RoundedCorners (@radius: 4px) { border-radius: @radius; } "; var individualContentFragments = LessCssHierarchicalParser.ParseIntoStructuredData( Parser.ParseLESS(content) ); Assert.Equal(2, individualContentFragments.Count()); Assert.Equal(3, individualContentFragments.ElementAt(1).SourceLineIndex); }
/// <summary> /// Apply a CSS string to a control. /// </summary> /// <param name="parent">The control to apply to.</param> /// <param name="cssString">The CSS content.</param> private static void ApplyInternal(object parent, string cssString) { var result = LessCssHierarchicalParser.ParseIntoStructuredData(Parser.ParseLESS(cssString)); foreach (Selector fragment in result) { foreach (ContainerFragment.WhiteSpaceNormalisedString selector in fragment.Selectors) { foreach (var item in fragment.ChildFragments) { var controls = GetControlsBySelector(parent, selector.Value); foreach (object control in controls) { if (control != null && item is StylePropertyValue styleProp) { SetProp(control, styleProp.Property.Value, styleProp.ValueSegments.Aggregate((x, y) => x + " " + y)); } } } } void SetProp(object target, string property, string valueString) { if (valueString == "") { return; } valueString = valueString.Trim(); var prop = target.GetType().GetProperty(property, BindingFlags.Public | BindingFlags.Instance); object value; if (prop == null) { return; } var eval = new Interpreter(); eval.Reference(prop.PropertyType); value = eval.Eval(valueString); prop.SetValue(target, value); } } }
/// <summary> /// This will throw a BrokenRuleEncounteredInFileException if any of the specified rules are broken /// </summary> public TextFileContents Load(string relativePath) { if (string.IsNullOrWhiteSpace(relativePath)) { throw new ArgumentException("Null/blank relativePath specified"); } // Several passes may be required for apply all of the rules - the first pass is to deal with rules that apply to individual files, // this is dealt with by wrapping the specified contentLoader in a CallbackMakingTextFileLoader and applying the rules as each file // is loaded. The callback from each Load call is also used to build up a representation of the combined content across all of the // files (before any processing or compilation work has been applied to the content). Subsequent passes (further down) will process // rules that apply to combined or compiled content. var loadedContentBuilder = new StringBuilder(); var rulesForIndividualFiles = _rules.Where(r => r.DoesThisRuleApplyTo(StyleSheetTypeOptions.Reset) || r.DoesThisRuleApplyTo(StyleSheetTypeOptions.Themes) || r.DoesThisRuleApplyTo(StyleSheetTypeOptions.Other) ); var individualFileValidatingAndTrackingContentLoader = new CallbackMakingTextFileLoader( _baseContentLoader, content => { if (content == null) { throw new ArgumentNullException("content"); } // Apply the rules for individual files (if any) if (rulesForIndividualFiles.Any()) { var individualContentFragments = LessCssHierarchicalParser.ParseIntoStructuredData( Parser.ParseLESS(content.Content) ); var styleSheetType = _styleSheetTypeDeterminer(content.RelativePath); foreach (var ruleForIndividualFiles in rulesForIndividualFiles) { if (ruleForIndividualFiles.DoesThisRuleApplyTo(styleSheetType)) { // If there's no callback then we're in the "throw as soon as validation rule broken" mode. If there IS a // callback then we want to gather ALL validation rule breaks and pass them to the caller if (_optionalBrokenFileCallback == null) { try { ruleForIndividualFiles.EnsureRulesAreMet(individualContentFragments); } catch (BrokenRuleEncounteredException e) { throw new BrokenRuleEncounteredInFileException(e, styleSheetType, content.RelativePath); } } else { foreach (var brokenRule in ruleForIndividualFiles.GetAnyBrokenRules(individualContentFragments)) { _optionalBrokenFileCallback( new BrokenRuleEncounteredInFileException(brokenRule, styleSheetType, content.RelativePath) ); } } } } } // Build up the combined content (I don't expect that parallel requests will be going on but considering the amount of // processing that will be going on with the rules validation, a tiny overhead from locking here for safety will have // no significant negative impact) lock (loadedContentBuilder) { // Using AppendLine rather than Append means that if any files have a single-line comment (eg. "// Comment") on // their last line then the content will be correctly interpreted as a comment when the combined content is // parsed (otherwise the first line of the next file will end up on the same line as the comment and some // of it may be incorrectly identified as comment content) loadedContentBuilder.AppendLine(content.Content); } } ); // Process the content by retrieving an ITextFileLoader through the provided compilerGenerator, using the content loader above // that will deal with individual-file rules and generate combined content for use below var compiler = _compilerGenerator(individualFileValidatingAndTrackingContentLoader); if (compiler == null) { throw new Exception("The provided compiledGenerator returned null - this is not valid"); } var compiledContent = compiler.Load(relativePath); // The source content has all been processed in terms of import flattening, LESS compilation (and the various other actions) // but rules that apply to Combined and Compiled content haven't been yet. // - If there are any rules that apply to Compiled content then the compiled content is parsed and the data passed through // each applicable rule var rulesForCompiledContent = _rules.Where(r => r.DoesThisRuleApplyTo(StyleSheetTypeOptions.Compiled)); if (rulesForCompiledContent.Any()) { var compiledContentFragments = LessCssHierarchicalParser.ParseIntoStructuredData( Parser.ParseLESS(compiledContent.Content) ); foreach (var ruleForCompiledContent in rulesForCompiledContent) { // If there's no callback then we're in the "throw as soon as validation rule broken" mode. If there IS a // callback then we want to gather ALL validation rule breaks and pass them to the caller if (_optionalBrokenFileCallback == null) { try { ruleForCompiledContent.EnsureRulesAreMet(compiledContentFragments); } catch (BrokenRuleEncounteredException e) { throw new BrokenRuleEncounteredInFileException(e, StyleSheetTypeOptions.Combined, relativePath); } } else { foreach (var brokenRule in ruleForCompiledContent.GetAnyBrokenRules(compiledContentFragments)) { _optionalBrokenFileCallback( new BrokenRuleEncounteredInFileException(brokenRule, StyleSheetTypeOptions.Combined, relativePath) ); } } } } // Similarly rules for Combined content are processed (the combined content is retrieved from the ContentRecordingTextFileLoader) var rulesForCombinedContent = _rules.Where(r => r.DoesThisRuleApplyTo(StyleSheetTypeOptions.Combined)); if (rulesForCombinedContent.Any()) { string combinedContent; lock (loadedContentBuilder) { combinedContent = loadedContentBuilder.ToString(); } if (combinedContent != "") { var combinedContentFragments = LessCssHierarchicalParser.ParseIntoStructuredData( Parser.ParseLESS(combinedContent) ); foreach (var ruleForCombinedContent in rulesForCombinedContent) { // If there's no callback then we're in the "throw as soon as validation rule broken" mode. If there IS a // callback then we want to gather ALL validation rule breaks and pass them to the caller if (_optionalBrokenFileCallback == null) { try { ruleForCombinedContent.EnsureRulesAreMet(combinedContentFragments); } catch (BrokenRuleEncounteredException e) { throw new BrokenRuleEncounteredInFileException(e, StyleSheetTypeOptions.Combined, relativePath); } } else { foreach (var brokenRule in ruleForCombinedContent.GetAnyBrokenRules(combinedContentFragments)) { _optionalBrokenFileCallback( new BrokenRuleEncounteredInFileException(brokenRule, StyleSheetTypeOptions.Combined, relativePath) ); } } } } } // Now that the rules validation process is complete, the compiled content can be returned return(compiledContent); }