diff --git a/esphome/components/web_server/__init__.py b/esphome/components/web_server/__init__.py
index 04f3cc5c043a..2f0d179ebaa9 100644
--- a/esphome/components/web_server/__init__.py
+++ b/esphome/components/web_server/__init__.py
@@ -3,7 +3,7 @@
from esphome.components import web_server_base
from esphome.components.web_server_base import CONF_WEB_SERVER_BASE_ID
from esphome.const import (
- CONF_CSS_URL, CONF_ID, CONF_JS_URL, CONF_PORT,
+ CONF_CSS_INCLUDE, CONF_CSS_URL, CONF_ID, CONF_JS_INCLUDE, CONF_JS_URL, CONF_PORT,
CONF_AUTH, CONF_USERNAME, CONF_PASSWORD)
from esphome.core import coroutine_with_priority
@@ -16,7 +16,9 @@
cv.GenerateID(): cv.declare_id(WebServer),
cv.Optional(CONF_PORT, default=80): cv.port,
cv.Optional(CONF_CSS_URL, default="https://esphome.io/_static/webserver-v1.min.css"): cv.string,
+ cv.Optional(CONF_CSS_INCLUDE): cv.file_,
cv.Optional(CONF_JS_URL, default="https://esphome.io/_static/webserver-v1.min.js"): cv.string,
+ cv.Optional(CONF_JS_INCLUDE): cv.file_,
cv.Optional(CONF_AUTH): cv.Schema({
cv.Required(CONF_USERNAME): cv.string_strict,
cv.Required(CONF_PASSWORD): cv.string_strict,
@@ -39,3 +41,11 @@ def to_code(config):
if CONF_AUTH in config:
cg.add(var.set_username(config[CONF_AUTH][CONF_USERNAME]))
cg.add(var.set_password(config[CONF_AUTH][CONF_PASSWORD]))
+ if CONF_CSS_INCLUDE in config:
+ cg.add_define('WEBSERVER_CSS_INCLUDE')
+ with open(config[CONF_CSS_INCLUDE], "r") as myfile:
+ cg.add(var.set_css_include(myfile.read()))
+ if CONF_JS_INCLUDE in config:
+ cg.add_define('WEBSERVER_JS_INCLUDE')
+ with open(config[CONF_JS_INCLUDE], "r") as myfile:
+ cg.add(var.set_js_include(myfile.read()))
diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp
index fcd83297e231..c0708b763fb7 100644
--- a/esphome/components/web_server/web_server.cpp
+++ b/esphome/components/web_server/web_server.cpp
@@ -60,7 +60,9 @@ UrlMatch match_url(const std::string &url, bool only_domain = false) {
}
void WebServer::set_css_url(const char *css_url) { this->css_url_ = css_url; }
+void WebServer::set_css_include(const char *css_include) { this->css_include_ = css_include; }
void WebServer::set_js_url(const char *js_url) { this->js_url_ = js_url; }
+void WebServer::set_js_include(const char *js_include) { this->js_include_ = js_include; }
void WebServer::setup() {
ESP_LOGCONFIG(TAG, "Setting up web server...");
@@ -133,9 +135,16 @@ void WebServer::handle_index_request(AsyncWebServerRequest *request) {
std::string title = App.get_name() + " Web Server";
stream->print(F("
"));
stream->print(title.c_str());
- stream->print(F(" print(this->css_url_);
- stream->print(F("\">"));
+ stream->print(F(""));
+#ifdef WEBSERVER_CSS_INCLUDE
+ stream->print(F(" "));
+#endif
+ if (strlen(this->css_url_) > 0) {
+ stream->print(F(" print(this->css_url_);
+ stream->print(F("\">"));
+ }
+ stream->print(F(""));
stream->print(title.c_str());
stream->print(F(" States Name State Actions "));
// All content is controlled and created by user - so allowing all origins is fine here.
@@ -175,13 +184,43 @@ void WebServer::handle_index_request(AsyncWebServerRequest *request) {
"REST API documentation."
"OTA Update "
- "Debug Log "
- ""));
+ "Debug Log "));
+#ifdef WEBSERVER_JS_INCLUDE
+ if (this->js_include_ != nullptr) {
+ stream->print(F(""));
+ }
+#endif
+ if (strlen(this->js_url_) > 0) {
+ stream->print(F(""));
+ }
+ stream->print(F("