aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael G. Martins <rafael@rafaelmartins.eng.br>2019-02-25 22:43:51 +0100
committerRafael G. Martins <rafael@rafaelmartins.eng.br>2020-01-12 12:37:11 +0100
commit7870e88f0653e6ac93c1f2e123aa9826778be376 (patch)
tree98d9c0840bf809ab5be36539680d0997762f3bb4
parenta45e7255cb89d76c4836e1cac073c2f941529e70 (diff)
downloadblogc-feature/sass.tar.gz
blogc-feature/sass.tar.bz2
blogc-feature/sass.zip
make: implemented optional sass support using libsassfeature/sass
pending: - tests for sass support - build tests on ci with and without libsass - documentation - support sass options in blogcfile
-rw-r--r--Makefile.am25
-rw-r--r--blogc.spec.in3
-rw-r--r--configure.ac12
-rw-r--r--src/blogc-make/ctx.c14
-rw-r--r--src/blogc-make/exec-native.c27
-rw-r--r--src/blogc-make/exec-native.h1
-rw-r--r--src/blogc-make/main.c6
-rw-r--r--src/blogc-make/rules.c17
-rw-r--r--src/blogc-make/sass.c148
-rw-r--r--src/blogc-make/sass.h18
-rw-r--r--src/blogc-make/settings.c4
-rw-r--r--src/blogc-make/settings.h1
12 files changed, 266 insertions, 10 deletions
diff --git a/Makefile.am b/Makefile.am
index 040f291..5fae160 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -60,6 +60,7 @@ noinst_HEADERS = \
src/blogc-make/httpd.h \
src/blogc-make/reloader.h \
src/blogc-make/rules.h \
+ src/blogc-make/sass.h \
src/blogc-make/settings.h \
src/blogc-make/utils.h \
src/blogc-runserver/httpd.h \
@@ -235,6 +236,16 @@ blogc_make_LDADD = \
libblogc_make.la \
libblogc_common.la \
$(NULL)
+
+if USE_LIBSASS
+blogc_make_CFLAGS += \
+ $(LIBSASS_CFLAGS) \
+ $(NULL)
+
+blogc_make_LDADD += \
+ $(LIBSASS_LIBS) \
+ $(NULL)
+endif
endif
if BUILD_MAKE_LIB
@@ -259,6 +270,20 @@ libblogc_make_la_LIBADD = \
$(PTHREAD_LIBS) \
libblogc_common.la \
$(NULL)
+
+if USE_LIBSASS
+libblogc_make_la_SOURCES += \
+ src/blogc-make/sass.c \
+ $(NULL)
+
+libblogc_make_la_CFLAGS += \
+ $(LIBSASS_CFLAGS) \
+ $(NULL)
+
+libblogc_make_la_LIBADD += \
+ $(LIBSASS_LIBS) \
+ $(NULL)
+endif
endif
diff --git a/blogc.spec.in b/blogc.spec.in
index 067ba89..f842cb9 100644
--- a/blogc.spec.in
+++ b/blogc.spec.in
@@ -6,7 +6,7 @@ Group: Applications/Text
Summary: A blog compiler
URL: @PACKAGE_URL@
Source0: https://github.com/blogc/blogc/releases/download/v@PACKAGE_VERSION@/blogc-@PACKAGE_VERSION@.tar.xz
-BuildRequires: gcc, bash, coreutils, diffutils
+BuildRequires: gcc, bash, coreutils, diffutils, libsass-devel
%if ! 0%{?el6}
BuildRequires: git, tar, make
%endif
@@ -32,6 +32,7 @@ blogc-git-receiver is a simple login shell/git hook to deploy blogc websites.
%package make
Summary: A simple build tool for blogc
Group: Development/Tools
+Requires: libsass
Requires: %{name} = %{version}-%{release}
Requires: %{name}-runserver = %{version}-%{release}
diff --git a/configure.ac b/configure.ac
index 880acf4..afe2cab 100644
--- a/configure.ac
+++ b/configure.ac
@@ -102,6 +102,8 @@ AC_ARG_ENABLE([make-embedded], AS_HELP_STRING([--enable-make-embedded],
[build blogc-make tool embedded on blogc binary]))
AC_ARG_ENABLE([make], AS_HELP_STRING([--enable-make],
[build blogc-make tool]))
+AC_ARG_WITH([libsass], AS_HELP_STRING([--without-libsass],
+ [disable blogc-make dependency on libsass]))
AS_IF([test "x$enable_make" = "xyes" -o "x$enable_make_embedded" = "xyes"], [
AC_CHECK_HEADERS([dirent.h fcntl.h libgen.h sys/stat.h sys/wait.h time.h unistd.h],, [
AC_MSG_ERROR([blogc-make tool requested but required headers not found])
@@ -118,10 +120,20 @@ AS_IF([test "x$enable_make" = "xyes" -o "x$enable_make_embedded" = "xyes"], [
MAKE_="enabled"
have_make=yes
])
+ AS_IF([test "x$with_libsass" != "xno"], [
+ PKG_CHECK_MODULES([LIBSASS], [libsass], [
+ MAKE_="${MAKE_} (with libsass)"
+ have_libsass=yes
+ AC_DEFINE([USE_LIBSASS], [], [Build blogc-make with libsass support])
+ ], [
+ have_libsass=no
+ ])
+ ])
])
AM_CONDITIONAL([BUILD_MAKE], [test "x$have_make" = "xyes"])
AM_CONDITIONAL([BUILD_MAKE_LIB], [test "x$have_make_lib" = "xyes"])
AM_CONDITIONAL([BUILD_MAKE_EMBEDDED], [test "x$have_make_embedded" = "xyes"])
+AM_CONDITIONAL([USE_LIBSASS], [test "x$have_libsass" = "xyes"])
RUNSERVER="disabled"
AC_ARG_ENABLE([runserver], AS_HELP_STRING([--enable-runserver],
diff --git a/src/blogc-make/ctx.c b/src/blogc-make/ctx.c
index 423b334..408b6f2 100644
--- a/src/blogc-make/ctx.c
+++ b/src/blogc-make/ctx.c
@@ -6,6 +6,10 @@
* See the file LICENSE.
*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /* HAVE_CONFIG_H */
+
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
@@ -192,6 +196,16 @@ bm_ctx_new(bm_ctx_t *base, const char *settings_file, const char *argv0,
}
free(content);
+#ifndef USE_LIBSASS
+ if (settings->sass != NULL) {
+ *err = bc_error_new_printf(BLOGC_MAKE_ERROR_SETTINGS,
+ "[sass] section found in %s, but blogc-make was built without "
+ "libsass support", settings_file);
+ bm_settings_free(settings);
+ return NULL;
+ }
+#endif
+
const char *template_dir = bc_trie_lookup(settings->settings, "template_dir");
if (template_dir == NULL)
template_dir = "";
diff --git a/src/blogc-make/exec-native.c b/src/blogc-make/exec-native.c
index 179216a..2417173 100644
--- a/src/blogc-make/exec-native.c
+++ b/src/blogc-make/exec-native.c
@@ -24,15 +24,9 @@
int
-bm_exec_native_cp(bm_filectx_t *source, bm_filectx_t *dest, bool verbose)
+bm_exec_native_mkdir_p(const char *filename)
{
- if (verbose)
- printf("Copying '%s' to '%s'\n", source->path, dest->path);
- else
- printf(" COPY %s\n", dest->short_path);
- fflush(stdout);
-
- char *fname = bc_strdup(dest->path);
+ char *fname = bc_strdup(filename);
for (char *tmp = fname; *tmp != '\0'; tmp++) {
if (*tmp != '/' && *tmp != '\\')
continue;
@@ -51,6 +45,23 @@ bm_exec_native_cp(bm_filectx_t *source, bm_filectx_t *dest, bool verbose)
}
free(fname);
+ return 0;
+}
+
+
+int
+bm_exec_native_cp(bm_filectx_t *source, bm_filectx_t *dest, bool verbose)
+{
+ if (verbose)
+ printf("Copying '%s' to '%s'\n", source->path, dest->path);
+ else
+ printf(" COPY %s\n", dest->short_path);
+ fflush(stdout);
+
+ int rv = bm_exec_native_mkdir_p(dest->path);
+ if (rv != 0)
+ return rv;
+
int fd_from = open(source->path, O_RDONLY);
if (fd_from < 0) {
fprintf(stderr, "blogc-make: error: failed to open source file to copy "
diff --git a/src/blogc-make/exec-native.h b/src/blogc-make/exec-native.h
index 56a1da1..0dfefcf 100644
--- a/src/blogc-make/exec-native.h
+++ b/src/blogc-make/exec-native.h
@@ -13,6 +13,7 @@
#include "../common/error.h"
#include "ctx.h"
+int bm_exec_native_mkdir_p(const char *filename);
int bm_exec_native_cp(bm_filectx_t *source, bm_filectx_t *dest, bool verbose);
bool bm_exec_native_is_empty_dir(const char *dir, bc_error_t **err);
int bm_exec_native_rm(const char *output_dir, bm_filectx_t *dest, bool verbose);
diff --git a/src/blogc-make/main.c b/src/blogc-make/main.c
index 5b4a030..f18b9df 100644
--- a/src/blogc-make/main.c
+++ b/src/blogc-make/main.c
@@ -75,7 +75,11 @@ main(int argc, char **argv)
print_help();
goto cleanup;
case 'v':
- printf("%s\n", PACKAGE_STRING);
+ printf(PACKAGE_STRING
+#ifdef USE_LIBSASS
+ "+libsass"
+#endif
+ "\n");
goto cleanup;
case 'D':
dev = true;
diff --git a/src/blogc-make/rules.c b/src/blogc-make/rules.c
index 06223c0..41e363d 100644
--- a/src/blogc-make/rules.c
+++ b/src/blogc-make/rules.c
@@ -6,6 +6,10 @@
* See the file LICENSE.
*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /* HAVE_CONFIG_H */
+
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
@@ -22,6 +26,10 @@
#include "utils.h"
#include "rules.h"
+#ifdef USE_LIBSASS
+#include "./sass.h"
+#endif
+
static void
posts_ordering(bm_ctx_t *ctx, bc_trie_t *variables, const char *variable)
@@ -850,6 +858,15 @@ const bm_rule_t rules[] = {
.exec_func = copy_exec,
.generate_files = true,
},
+#ifdef USE_LIBSASS
+ {
+ .name = "sass",
+ .help = "build CSS stylesheets from Sass (.scss) sources",
+ .outputlist_func = bm_sass_outputlist,
+ .exec_func = bm_sass_exec,
+ .generate_files = true,
+ },
+#endif
{
.name = "clean",
.help = "clean built files and empty directories in output directory",
diff --git a/src/blogc-make/sass.c b/src/blogc-make/sass.c
new file mode 100644
index 0000000..da4b8b6
--- /dev/null
+++ b/src/blogc-make/sass.c
@@ -0,0 +1,148 @@
+/*
+ * blogc: A blog compiler.
+ * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
+ *
+ * This program can be distributed under the terms of the BSD License.
+ * See the file LICENSE.
+ */
+
+#include <sass.h>
+#include <errno.h>
+#include <libgen.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "ctx.h"
+#include "exec-native.h"
+#include "rules.h"
+#include "./sass.h"
+#include "../common/utils.h"
+
+
+bc_slist_t*
+bm_sass_outputlist(bm_ctx_t *ctx)
+{
+ if (ctx == NULL || ctx->settings == NULL || ctx->settings->sass == NULL)
+ return NULL;
+
+ bc_slist_t *rv = NULL;
+
+ for (size_t i = 0; ctx->settings->sass[i] != NULL; i++) {
+ char *t = bc_strdup(ctx->settings->sass[i]);
+ for (int i = strlen(t); i >= 0 ; i--) {
+ if (t[i] == '.') {
+ t[i] = '\0';
+ break;
+ }
+ }
+
+ char *f = bc_strdup_printf("%s/%s.css", ctx->short_output_dir, t);
+ free(t);
+ rv = bc_slist_append(rv, bm_filectx_new(ctx, f, NULL, NULL));
+ free(f);
+ }
+
+ return rv;
+}
+
+
+int
+bm_sass_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args)
+{
+ if (ctx == NULL || ctx->settings == NULL || ctx->settings->sass == NULL)
+ return 0;
+
+ int rv = 0;
+
+ size_t i = 0;
+ bc_slist_t *o = outputs;
+
+ for (; ctx->settings->sass[i] != NULL, o != NULL; i++, o = o->next) {
+ bm_filectx_t *o_fctx = o->data;
+ if (o_fctx == NULL)
+ continue;
+
+ if (bc_str_starts_with(basename(ctx->settings->sass[i]), "_")) {
+ fprintf(stderr, "blogc-make: error: sass: Mixins must be included "
+ "by other files (%s)\n", ctx->settings->sass[i]);
+ return 3;
+ }
+ if (!bc_str_ends_with(ctx->settings->sass[i], ".scss")) {
+ fprintf(stderr, "blogc-make: error: sass: Only .scss Sass sources "
+ "are supported (%s)\n", ctx->settings->sass[i]);
+ return 3;
+ }
+
+ bm_filectx_t *f = bm_filectx_new(ctx, ctx->settings->sass[i], NULL, NULL);
+
+ struct Sass_File_Context *fctx = sass_make_file_context(f->path);
+ struct Sass_Context *sctx = sass_file_context_get_context(fctx);
+ struct Sass_Compiler *comp = sass_make_file_compiler(fctx);
+ struct Sass_Options *opts = sass_context_get_options(sctx);
+ sass_option_set_output_style(opts, SASS_STYLE_COMPRESSED);
+ char *sass_dir = bc_strdup_printf("%s/sass", ctx->root_dir);
+ sass_option_push_include_path(opts, sass_dir);
+ free(sass_dir);
+ sass_dir = bc_strdup_printf("%s/_sass", ctx->root_dir);
+ sass_option_push_include_path(opts, sass_dir);
+ free(sass_dir);
+
+ bc_slist_t *sources = NULL;
+
+ rv = sass_compiler_parse(comp);
+ if (rv != 0 || 0 != sass_context_get_error_status(sctx)) {
+ fprintf(stderr, "blogc-make: error: sass: %s\n%s",
+ o_fctx->path, sass_context_get_error_message(sctx));
+ rv = 3;
+ goto clean;
+ }
+
+ char **inc = sass_context_get_included_files(sctx);
+ for (size_t i = 0; inc != NULL && inc[i] != NULL; i++) {
+ sources = bc_slist_append(sources, bm_filectx_new(ctx, inc[i], NULL, NULL));
+ }
+
+ if (!bm_rule_need_rebuild(sources, ctx->settings_fctx, NULL, NULL, o_fctx, false))
+ goto clean;
+
+ if (ctx->verbose)
+ printf("Compiling '%s' to '%s'\n", f->path, o_fctx->path);
+ else
+ printf(" SASS %s\n", o_fctx->short_path);
+ fflush(stdout);
+
+ rv = sass_compiler_execute(comp);
+ if (rv != 0 || 0 != sass_context_get_error_status(sctx)) {
+ fprintf(stderr, "blogc-make: error: sass: %s\n%s",
+ o_fctx->path, sass_context_get_error_message(sctx));
+ rv = 3;
+ goto clean;
+ }
+
+ rv = bm_exec_native_mkdir_p(o_fctx->path);
+ if (rv != 0)
+ goto clean;
+
+ FILE *fp = fopen(o_fctx->path, "w");
+ if (fp == NULL) {
+ fprintf(stderr, "blogc-make: error: sass: failed to open output "
+ "file (%s): %s\n", o_fctx->path, strerror(errno));
+ rv = 3;
+ goto clean;
+ }
+
+ fputs(sass_context_get_output_string(sctx), fp);
+ fclose(fp);
+
+clean:
+ bm_filectx_free(f);
+ bc_slist_free_full(sources, (bc_free_func_t) bm_filectx_free);
+ sass_delete_compiler(comp);
+ sass_delete_file_context(fctx);
+
+ if (rv != 0)
+ return rv;
+ }
+
+ return 0;
+}
diff --git a/src/blogc-make/sass.h b/src/blogc-make/sass.h
new file mode 100644
index 0000000..351b736
--- /dev/null
+++ b/src/blogc-make/sass.h
@@ -0,0 +1,18 @@
+/*
+ * blogc: A blog compiler.
+ * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
+ *
+ * This program can be distributed under the terms of the BSD License.
+ * See the file LICENSE.
+ */
+
+#ifndef _MAKE_SASS_H
+#define _MAKE_SASS_H
+
+#include "ctx.h"
+#include "../common/utils.h"
+
+bc_slist_t* bm_sass_outputlist(bm_ctx_t *ctx);
+int bm_sass_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args);
+
+#endif /* _MAKE_SASS_H */
diff --git a/src/blogc-make/settings.c b/src/blogc-make/settings.c
index be976e3..f13d5b2 100644
--- a/src/blogc-make/settings.c
+++ b/src/blogc-make/settings.c
@@ -72,6 +72,7 @@ static const char* list_sections[] = {
"copy",
"copy_files", // backward compatibility
"tags",
+ "sass",
NULL,
};
@@ -97,6 +98,7 @@ bm_settings_parse(const char *content, size_t content_len, bc_error_t **err)
rv->pages = NULL;
rv->copy = NULL;
rv->tags = NULL;
+ rv->sass = NULL;
// this is some code for compatibility with the [environment] section,
// even if I never released a version with it, but some people is using
@@ -159,6 +161,7 @@ bm_settings_parse(const char *content, size_t content_len, bc_error_t **err)
rv->posts = bc_config_get_list(config, "posts");
rv->pages = bc_config_get_list(config, "pages");
rv->tags = bc_config_get_list(config, "tags");
+ rv->sass = bc_config_get_list(config, "sass");
// this is for backward compatibility too.
rv->copy = bc_config_get_list(config, "copy");
@@ -184,5 +187,6 @@ bm_settings_free(bm_settings_t *settings)
bc_strv_free(settings->pages);
bc_strv_free(settings->copy);
bc_strv_free(settings->tags);
+ bc_strv_free(settings->sass);
free(settings);
}
diff --git a/src/blogc-make/settings.h b/src/blogc-make/settings.h
index 69fdbb6..8060963 100644
--- a/src/blogc-make/settings.h
+++ b/src/blogc-make/settings.h
@@ -20,6 +20,7 @@ typedef struct {
char **pages;
char **copy;
char **tags;
+ char **sass;
} bm_settings_t;
bm_settings_t* bm_settings_parse(const char *content, size_t content_len,