blogger_theme 5.0.0
blogger_theme: ^5.0.0 copied to clipboard
A lightweight standalone Dart library to design Blogger themes with Jaspr-like syntax.
example/main.dart
import 'package:blogger_theme/blogger_theme.dart';
void main() {
final theme = BloggerTheme(
attributes: {
// static compiler flags
'b:responsive': 'true',
'b:defaultwidgetversion': '2',
'b:layoutsversion': '3',
'b:css': 'false', // Disables default Blogger CSS globally
/// this removes that <script src=".../widgets.js">
/// for Better do try replace the closing </body> with
/// => <!--</body>--></body>
/// => this will make those scripts as comment
/// Reference: [JS as Comment] Below
// 'b:js': 'false', // Disables default widgets.js globally
//
'xmlns': 'http://www.w3.org/1999/xhtml',
'xmlns:b': 'http://www.google.com/2005/gml/b',
'xmlns:data': 'http://www.google.com/2005/gml/data',
'xmlns:expr': 'http://www.google.com/2005/gml/expr',
},
// Reset attributes to clean XML output for strict AMP validation
children: [
BAttr(name: 'xmlns', value: ''),
BAttr(name: 'xmlns:b', value: ''),
BAttr(name: 'xmlns:expr', value: ''),
BAttr(name: 'xmlns:data', value: ''),
// Conditionally adds amp="amp" (or lightning bolt symbol ⚡) to <html> on mobile requests
BAttr(cond: 'data:blog.isMobileRequest', name: 'amp', value: 'amp'),
// Alternatively, you can use the ⚡ symbol:
// BAttr(cond: 'data:blog.isMobileRequest', name: '⚡', value: '⚡'),
// BClass(exprName: '"nJs" + (data:blog.isMobileRequest ? " amp" : "")'), // TODO:[Kept to show we can assign class ]
],
head: [
Meta(attributes: {"expr:charset": "data:blog.encoding"}),
Script(
attributes: {
'async': 'async',
'src': 'https://cdn.ampproject.org/v0.js',
},
),
Meta(
attributes: {
"name": "viewport",
"content": "width=device-width,minimum-scale=1,initial-scale=1",
},
),
Link(
attributes: {"rel": "canonical", "expr:href": "data:blog.canonicalUrl"},
),
Link(
attributes: {
"rel": "amphtml",
"expr:href": 'data:blog.canonicalUrl params { m: "1" }',
},
),
Title(children: [Text('Generated Blogger Theme')]),
// RawText(
// '<style amp-boilerplate="amp-boilerplate">body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style>'
// '<noscript><style amp-boilerplate="amp-boilerplate">body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>',
// ),
// OR For Better Tooling Support [In Future]
Style(
attributes: {"amp-boilerplate": "amp-boilerplate"},
children: [
Text(
'body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}',
escape: false,
),
],
),
Noscript(
children: [
Style(
attributes: {"amp-boilerplate": "amp-boilerplate"},
children: [
Text(
'body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}',
escape: false,
),
],
),
],
),
// For AMP compliance, keep the CSS string empty ("") and use Style with `amp-custom` attribute and there put your css (limit 50KB)
BIf(
cond: false.toString(),
children: [
BSkin(
"",
variables: [
// Text('''
// /*
// <!-- Variable definitions -->
// <Variable name="keycolor" description="Main Color" type="color" default="#8abc0d" value="#ee582e"/>
// */
// '''),
BVariable(
name: "keycolor", // Variable identifier used in CSS
description: "Main Color", // Title shown in Blogger Designer
type: "color", // Tells Blogger to render a color picker
defaultValue: "#8abc0d", // Default color
value: "#ee582e",
),
// TODO: Add variables and Group here
// Disable default b:skin CSS output while preserving custom Blogger theme variables.
// Keep the CSS string empty ("") for strict AMP validation.
],
),
],
),
// Place Use custom styles in a <style amp-custom> tag instead (50 KB limit).
Style(
attributes: {
'amp-custom': 'amp-custom',
'id': "page-skin-1",
"type": "text/css",
},
children: [
// as we made skin:vars as vars there in top with
// Your Custom css styles here, for example:
Text(
'''
:root {
--keycolor: <data:skin.vars.keycolor/>;
}
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
h1 {
color: var(--keycolor);
}
''',
escape: false, // This is Important as if escaped
//then <data:skin.vars.keycolor/> will be converted and that will not work as aspected
),
],
),
// here we have a Issue with amp if
// your Earnings Tab > is Enabled from Blogger Dashboard,
// then you need to remove the Adsense from that Earning Tab
// and trick it to use with other methods. and also make sure you
// don't click on that `Connect Adsense` button from Blogger Dashboard,z
],
body: [const BlogLayout()],
);
var xml = theme.generate();
// Reference: [JS as Comment]
xml = xml.replaceLast(
'</body>',
// or use => <!--</body>--></body>
'''<textarea id='template_widgets_js' disabled='disabled' readonly='readonly' hidden='hidden' aria-hidden='true' class='notranslate'>
</body>
</textarea>
</body>''',
);
print(xml);
}
class BlogLayout extends Component {
const BlogLayout();
@override
Iterable<Component> build() => [
Div(
attributes: {'class': 'wrapper-pane'},
children: [
BSection(
id: 'header-area',
className: 'header-section',
maxwidgets: 1,
showaddelement: true,
children: [],
),
BSection(
id: 'main-content',
className: 'main-content-section',
maxwidgets: 1,
showaddelement: true,
children: [
H1(
children: [
Text('My AMP Blogger Theme having H1 Keycolor in '),
//<b:eval expr="data:skin.vars.keycolor"/></h1>
BEval(expr: 'data:skin.vars.keycolor'),
],
),
],
),
],
),
];
}
extension StringUtils on String {
/// Replaces the last occurrence of [from] with [to].
String replaceLast(Pattern from, String to) {
final match = from.allMatches(this).lastOrNull;
if (match == null) return this;
return replaceRange(match.start, match.end, to);
}
}