Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Using_media_queries #608

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 28 additions & 46 deletions webf/example/assets/bundle.html
Original file line number Diff line number Diff line change
@@ -1,51 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<style>
.container {
margin: 64px 0 32px;
text-align: center;

<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
div.example {
background-color: lightblue;
padding: 20px;
}

@media only screen and (max-width: 400px) and (min-width: 100px) {
div.example {
background-color: blue;
}
.logo {
width: 128px;
}

@media only screen and (prefers-color-scheme: dark) {
div.example {
background-color: rosybrown;
}
.p {
color: #ff6633;
line-height: 1.7em;
}
@keyframes example {
from {
background-color: red;
width: 100px;
}
to {
background-color: yellow;
width: 200px;
}
}
.icons {
text-align: center;
padding: 8px 0;
}
.icon {
width: 24px;
height: 24px;
margin-right: 4px;
}
</style>
</head>
<body>
<div class="container">
<img class="logo" src="./webf.png" />
</div>
<div class="icons">
<svg class="icon" viewBox="0 0 1024 1024"><path d="M64 512c0 195.2 124.8 361.6 300.8 422.4 22.4 6.4 19.2-9.6 19.2-22.4v-76.8c-134.4 16-140.8-73.6-150.4-89.6-19.2-32-60.8-38.4-48-54.4 32-16 64 3.2 99.2 57.6 25.6 38.4 76.8 32 105.6 25.6 6.4-22.4 19.2-44.8 35.2-60.8-144-22.4-201.6-108.8-201.6-211.2 0-48 16-96 48-131.2-22.4-60.8 0-115.2 3.2-121.6 57.6-6.4 118.4 41.6 124.8 44.8 32-9.6 70.4-12.8 112-12.8 41.6 0 80 6.4 112 12.8 12.8-9.6 67.2-48 121.6-44.8 3.2 6.4 25.6 57.6 6.4 118.4 32 38.4 48 83.2 48 131.2 0 102.4-57.6 188.8-201.6 214.4 22.4 22.4 38.4 54.4 38.4 92.8v112c0 9.6 0 19.2 16 19.2C832 876.8 960 710.4 960 512c0-246.4-201.6-448-448-448S64 265.6 64 512z" fill="#040000" p-id="3824"></path></svg>
<img class="icon" src="./js-icon.svg" />
<svg class="icon" viewBox="0 0 1024 1024"><path d="M89.088 59.392l62.464 803.84c1.024 12.288 9.216 22.528 20.48 25.6L502.784 993.28c6.144 2.048 12.288 2.048 18.432 0l330.752-104.448c11.264-4.096 19.456-14.336 20.48-25.6l62.464-803.84c1.024-17.408-12.288-31.744-29.696-31.744H118.784c-17.408 0-31.744 14.336-29.696 31.744z" fill="#FC490B" p-id="5421"></path><path d="M774.144 309.248h-409.6l12.288 113.664h388.096l-25.6 325.632-227.328 71.68-227.328-71.68-13.312-169.984h118.784v82.944l124.928 33.792 123.904-33.792 10.24-132.096H267.264L241.664 204.8h540.672z" fill="#FFFFFF" p-id="5422"></path></svg>
</div>
<script>
console.log('Welcome to webf!');
</script>
<script src="./bundle.js"></script>
</body>
}
</style>
<!-- <link rel="stylesheet" media="screen and (max-width: 500px) and (min-width: 200px)" href="http://10.15.48.109:8080/widescreen.css" /> -->
</head>

<body>
<div class="example" style="right: 33.1094px; opacity: 1; color: beige">
Example DIV.
</div>
</body>

</html>
3 changes: 2 additions & 1 deletion webf/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ class FirstPageState extends State<FirstPage> {
super.didChangeDependencies();
controller = WebFController(
context,
isDarkMode: MediaQuery.of(context).platformBrightness == Brightness.dark,
devToolsService: ChromeDevToolsService(),
);
controller.preload(WebFBundle.fromUrl('assets:assets/bundle.html'));
controller.preload(WebFBundle.fromUrl('assets:assets/bundle.html'), viewportSize: MediaQuery.of(context).size);
}

@override
Expand Down
158 changes: 158 additions & 0 deletions webf/lib/src/css/css_rule.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,161 @@ class CSSFontFaceRule extends CSSRule {
return '@font-face';
}
}


class CSSMediaDirective extends CSSRule {
final CSSMediaQuery? cssMediaQuery;
final List<CSSRule>? rules;

CSSMediaDirective(this.cssMediaQuery, this.rules) : super();

set rules(List<CSSRule>? rules) {
this.rules = rules;
}

@override
int get type => CSSRule.MEDIA_RULE;

List<CSSRule>? getValidMediaRules(double? windowWidth, double? windowHeight, bool isDarkMode) {
List<CSSRule>? _mediaRules = [];
// print('--------- --------- --------- --------- CSSMediaDirective start--------- --------- --------- --------- ');
if (rules == null) {
return _mediaRules;
}
if (cssMediaQuery == null) {
return rules;
}
// bool isMediaTypeNotOp = cssMediaQuery._mediaUnary == TokenKind.MEDIA_OP_ONLY;
//w3c has media type screen/print/speech/all, but webf only work on screen and all
String? mediaType = cssMediaQuery!._mediaType?.name;
if (mediaType != null && mediaType != MediaType.SCREEN && mediaType != MediaType.ALL) {
return _mediaRules;
}
List<bool> conditions = [];
List<bool> ops = [];
for (CSSMediaExpression expression in cssMediaQuery!.expressions) {
// [max-width: 1800px, min-width: 450px]
if (expression.mediaStyle != null) {
dynamic maxAspectRatio = expression.mediaStyle!['max-aspect-ratio'];
if (maxAspectRatio != null && windowWidth != null && windowHeight != null) {
double? maxAPS;
if (maxAspectRatio is String) {
maxAPS = parseStringToDouble(maxAspectRatio);
} else if (maxAspectRatio is double) {
maxAPS = maxAspectRatio;
}
if (maxAPS != null) {
bool condition = windowWidth / windowHeight <= maxAPS;
conditions.add(condition);
ops.add(expression.op == MediaOperator.AND);
}
}
dynamic minAspectRatio = expression.mediaStyle!['min-aspect-ratio'];
if (minAspectRatio != null && windowWidth != null && windowHeight != null) {
double? minAPS;
if (minAspectRatio is String) {
minAPS = parseStringToDouble(minAspectRatio);
} else if (minAspectRatio is double) {
minAPS = minAspectRatio;
}
if (minAPS != null) {
bool condition = windowWidth / windowHeight >= minAPS;
conditions.add(condition);
ops.add(expression.op == MediaOperator.AND);
}
}
dynamic maxWidth = expression.mediaStyle!['max-width'];
if (windowWidth != null && maxWidth != null) {
double maxWidthValue = CSSLength.parseLength(maxWidth, null).value ?? -1;
bool condition = windowWidth < maxWidthValue;
conditions.add(condition);
ops.add(expression.op == MediaOperator.AND);
}
dynamic minWidth = expression.mediaStyle!['min-width'];
if (windowWidth != null && minWidth != null) {
double minWidthValue = CSSLength.parseLength(minWidth, null).value ?? -1;
bool condition = windowWidth > minWidthValue;
conditions.add(condition);
ops.add(expression.op == MediaOperator.AND);
}
dynamic prefersColorScheme = expression.mediaStyle!['prefers-color-scheme'];
if (prefersColorScheme != null) {
bool isMediaDarkMode = prefersColorScheme == 'dark';
bool condition = isMediaDarkMode == isDarkMode;
conditions.add(condition);
ops.add(expression.op == MediaOperator.AND);
}
}
}
bool isValid = true;
for (int i = 0; i < conditions.length; i ++) {
bool con = conditions[i];
bool isAnd = ops[i];
if (isAnd) {
isValid = isValid && con;
} else {
isValid = isValid || con;
}
}
if (isValid) {
_mediaRules = rules;
}
// print('--------- --------- --------- --------- CSSMediaDirective end--------- --------- --------- --------- ');
return _mediaRules;
}

double? parseStringToDouble(String str) {
try {
if (str.contains('/')) { // 8/5
List<String> parts = str.split('/');
double num1 = double.parse(parts[0]);
double num2 = double.parse(parts[1]);
return num1 / num2;
}
return double.parse(str);
} catch (e) {
print('parseStringToDouble $e');
}
return null;
}
}

/// MediaQuery grammar:
///
/// : [ONLY | NOT]? S* media_type S* [ AND S* media_expression ]*
/// | media_expression [ AND S* media_expression ]*
/// media_type
/// : IDENT
/// media_expression
/// : '(' S* media_feature S* [ ':' S* expr ]? ')' S*
/// media_feature
/// : IDENT
class CSSMediaQuery extends TreeNode {
/// not, only or no operator.
final int _mediaUnary;
final Identifier? _mediaType;
final List<CSSMediaExpression> expressions;

CSSMediaQuery(
this._mediaUnary, this._mediaType, this.expressions)
: super();

bool get hasMediaType => _mediaType != null;
String get mediaType => _mediaType!.name;

bool get hasUnary => _mediaUnary != -1;
String get unary =>
TokenKind.idToValue(TokenKind.MEDIA_OPERATORS, _mediaUnary)!
.toUpperCase();
}


/// MediaExpression grammar:
///
/// '(' S* media_feature S* [ ':' S* expr ]? ')' S*
class CSSMediaExpression extends TreeNode {
final String op;
final Map<String, String>? mediaStyle;

CSSMediaExpression(this.op, this.mediaStyle) : super();
}
Loading
Loading