aboutsummaryrefslogtreecommitdiffstats
path: root/src/blogc-make/sass.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/blogc-make/sass.c')
-rw-r--r--src/blogc-make/sass.c148
1 files changed, 148 insertions, 0 deletions
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;
+}