思源笔记折腾记录 -html 块 - 主题 css 颜色选择器

本贴最后更新于 635 天前,其中的信息可能已经事过景迁

首先是引入依赖,这里我们需要一个颜色选择器来修改主题样式,就用跟思源本身一样的 pickr 好了:

import Pickr from "@simonwep/pickr/dist/pickr.es5.min";
let pickClassic = `
.pickr{position:relative;overflow:visible;transform:translateY(0)}.pickr *{box-sizing:border-box;outline:none;border:none;-webkit-appearance:none}.pickr .pcr-button{position:relative;height:2em;width:2em;padding:0.5em;cursor:pointer;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","Roboto","Helvetica Neue",Arial,sans-serif;border-radius:.15em;background:url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50" stroke="%2342445A" stroke-width="5px" stroke-linecap="round"><path d="M45,45L5,5"></path><path d="M45,5L5,45"></path></svg>') no-repeat center;background-size:0;transition:all 0.3s}.pickr .pcr-button::before{position:absolute;content:'';top:0;left:0;width:100%;height:100%;background:url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2"><path fill="white" d="M1,0H2V1H1V0ZM0,1H1V2H0V1Z"/><path fill="gray" d="M0,0H1V1H0V0ZM1,1H2V2H1V1Z"/></svg>');background-size:.5em;border-radius:.15em;z-index:-1}.pickr .pcr-button::before{z-index:initial}.pickr .pcr-button::after{position:absolute;content:'';top:0;left:0;height:100%;width:100%;transition:background 0.3s;background:var(--pcr-color);border-radius:.15em}.pickr .pcr-button.clear{background-size:70%}.pickr .pcr-button.clear::before{opacity:0}.pickr .pcr-button.clear:focus{box-shadow:0 0 0 1px rgba(255,255,255,0.85),0 0 0 3px var(--pcr-color)}.pickr .pcr-button.disabled{cursor:not-allowed}.pickr *,.pcr-app *{box-sizing:border-box;outline:none;border:none;-webkit-appearance:none}.pickr input:focus,.pickr input.pcr-active,.pickr button:focus,.pickr button.pcr-active,.pcr-app input:focus,.pcr-app input.pcr-active,.pcr-app button:focus,.pcr-app button.pcr-active{box-shadow:0 0 0 1px rgba(255,255,255,0.85),0 0 0 3px var(--pcr-color)}.pickr .pcr-palette,.pickr .pcr-slider,.pcr-app .pcr-palette,.pcr-app .pcr-slider{transition:box-shadow 0.3s}.pickr .pcr-palette:focus,.pickr .pcr-slider:focus,.pcr-app .pcr-palette:focus,.pcr-app .pcr-slider:focus{box-shadow:0 0 0 1px rgba(255,255,255,0.85),0 0 0 3px rgba(0,0,0,0.25)}.pcr-app{position:fixed;display:flex;flex-direction:column;z-index:10000;border-radius:0.1em;background:#fff;opacity:0;visibility:hidden;transition:opacity 0.3s, visibility 0s 0.3s;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","Roboto","Helvetica Neue",Arial,sans-serif;box-shadow:0 0.15em 1.5em 0 rgba(0,0,0,0.1),0 0 1em 0 rgba(0,0,0,0.03);left:0;top:0}.pcr-app.visible{transition:opacity 0.3s;visibility:visible;opacity:1}.pcr-app .pcr-swatches{display:flex;flex-wrap:wrap;margin-top:0.75em}.pcr-app .pcr-swatches.pcr-last{margin:0}@supports (display: grid){.pcr-app .pcr-swatches{display:grid;align-items:center;grid-template-columns:repeat(auto-fit, 1.75em)}}.pcr-app .pcr-swatches>button{font-size:1em;position:relative;width:calc(1.75em - 5px);height:calc(1.75em - 5px);border-radius:0.15em;cursor:pointer;margin:2.5px;flex-shrink:0;justify-self:center;transition:all 0.15s;overflow:hidden;background:transparent;z-index:1}.pcr-app .pcr-swatches>button::before{position:absolute;content:'';top:0;left:0;width:100%;height:100%;background:url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2"><path fill="white" d="M1,0H2V1H1V0ZM0,1H1V2H0V1Z"/><path fill="gray" d="M0,0H1V1H0V0ZM1,1H2V2H1V1Z"/></svg>');background-size:6px;border-radius:.15em;z-index:-1}.pcr-app .pcr-swatches>button::after{content:'';position:absolute;top:0;left:0;width:100%;height:100%;background:var(--pcr-color);border:1px solid rgba(0,0,0,0.05);border-radius:0.15em;box-sizing:border-box}.pcr-app .pcr-swatches>button:hover{filter:brightness(1.05)}.pcr-app .pcr-swatches>button:not(.pcr-active){box-shadow:none}.pcr-app .pcr-interaction{display:flex;flex-wrap:wrap;align-items:center;margin:0 -0.2em 0 -0.2em}.pcr-app .pcr-interaction>*{margin:0 0.2em}.pcr-app .pcr-interaction input{letter-spacing:0.07em;font-size:0.75em;text-align:center;cursor:pointer;color:#75797e;background:#f1f3f4;border-radius:.15em;transition:all 0.15s;padding:0.45em 0.5em;margin-top:0.75em}.pcr-app .pcr-interaction input:hover{filter:brightness(0.975)}.pcr-app .pcr-interaction input:focus{box-shadow:0 0 0 1px rgba(255,255,255,0.85),0 0 0 3px rgba(66,133,244,0.75)}.pcr-app .pcr-interaction .pcr-result{color:#75797e;text-align:left;flex:1 1 8em;min-width:8em;transition:all 0.2s;border-radius:.15em;background:#f1f3f4;cursor:text}.pcr-app .pcr-interaction .pcr-result::-moz-selection{background:#4285f4;color:#fff}.pcr-app .pcr-interaction .pcr-result::selection{background:#4285f4;color:#fff}.pcr-app .pcr-interaction .pcr-type.active{color:#fff;background:#4285f4}.pcr-app .pcr-interaction .pcr-save,.pcr-app .pcr-interaction .pcr-cancel,.pcr-app .pcr-interaction .pcr-clear{color:#fff;width:auto}.pcr-app .pcr-interaction .pcr-save,.pcr-app .pcr-interaction .pcr-cancel,.pcr-app .pcr-interaction .pcr-clear{color:#fff}.pcr-app .pcr-interaction .pcr-save:hover,.pcr-app .pcr-interaction .pcr-cancel:hover,.pcr-app .pcr-interaction .pcr-clear:hover{filter:brightness(0.925)}.pcr-app .pcr-interaction .pcr-save{background:#4285f4}.pcr-app .pcr-interaction .pcr-clear,.pcr-app .pcr-interaction .pcr-cancel{background:#f44250}.pcr-app .pcr-interaction .pcr-clear:focus,.pcr-app .pcr-interaction .pcr-cancel:focus{box-shadow:0 0 0 1px rgba(255,255,255,0.85),0 0 0 3px rgba(244,66,80,0.75)}.pcr-app .pcr-selection .pcr-picker{position:absolute;height:18px;width:18px;border:2px solid #fff;border-radius:100%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.pcr-app .pcr-selection .pcr-color-palette,.pcr-app .pcr-selection .pcr-color-chooser,.pcr-app .pcr-selection .pcr-color-opacity{position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:flex;flex-direction:column;cursor:grab;cursor:-webkit-grab}.pcr-app .pcr-selection .pcr-color-palette:active,.pcr-app .pcr-selection .pcr-color-chooser:active,.pcr-app .pcr-selection .pcr-color-opacity:active{cursor:grabbing;cursor:-webkit-grabbing}.pcr-app[data-theme='classic']{width:28.5em;max-width:95vw;padding:0.8em}.pcr-app[data-theme='classic'] .pcr-selection{display:flex;justify-content:space-between;flex-grow:1}.pcr-app[data-theme='classic'] .pcr-selection .pcr-color-preview{position:relative;z-index:1;width:2em;display:flex;flex-direction:column;justify-content:space-between;margin-right:0.75em}.pcr-app[data-theme='classic'] .pcr-selection .pcr-color-preview::before{position:absolute;content:'';top:0;left:0;width:100%;height:100%;background:url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2"><path fill="white" d="M1,0H2V1H1V0ZM0,1H1V2H0V1Z"/><path fill="gray" d="M0,0H1V1H0V0ZM1,1H2V2H1V1Z"/></svg>');background-size:.5em;border-radius:.15em;z-index:-1}.pcr-app[data-theme='classic'] .pcr-selection .pcr-color-preview .pcr-last-color{cursor:pointer;border-radius:0.15em 0.15em 0 0;z-index:2}.pcr-app[data-theme='classic'] .pcr-selection .pcr-color-preview .pcr-current-color{border-radius:0 0 0.15em 0.15em}.pcr-app[data-theme='classic'] .pcr-selection .pcr-color-preview .pcr-last-color,.pcr-app[data-theme='classic'] .pcr-selection .pcr-color-preview .pcr-current-color{background:var(--pcr-color);width:100%;height:50%}.pcr-app[data-theme='classic'] .pcr-selection .pcr-color-palette{width:100%;height:8em;z-index:1}.pcr-app[data-theme='classic'] .pcr-selection .pcr-color-palette .pcr-palette{flex-grow:1;border-radius:.15em}.pcr-app[data-theme='classic'] .pcr-selection .pcr-color-palette .pcr-palette::before{position:absolute;content:'';top:0;left:0;width:100%;height:100%;background:url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2"><path fill="white" d="M1,0H2V1H1V0ZM0,1H1V2H0V1Z"/><path fill="gray" d="M0,0H1V1H0V0ZM1,1H2V2H1V1Z"/></svg>');background-size:.5em;border-radius:.15em;z-index:-1}.pcr-app[data-theme='classic'] .pcr-selection .pcr-color-chooser,.pcr-app[data-theme='classic'] .pcr-selection .pcr-color-opacity{margin-left:0.75em}.pcr-app[data-theme='classic'] .pcr-selection .pcr-color-chooser .pcr-picker,.pcr-app[data-theme='classic'] .pcr-selection .pcr-color-opacity .pcr-picker{left:50%;transform:translateX(-50%)}.pcr-app[data-theme='classic'] .pcr-selection .pcr-color-chooser .pcr-slider,.pcr-app[data-theme='classic'] .pcr-selection .pcr-color-opacity .pcr-slider{width:8px;flex-grow:1;border-radius:50em}.pcr-app[data-theme='classic'] .pcr-selection .pcr-color-chooser .pcr-slider{background:linear-gradient(to bottom, red, #ff0, lime, cyan, blue, #f0f, red)}.pcr-app[data-theme='classic'] .pcr-selection .pcr-color-opacity .pcr-slider{background:linear-gradient(to bottom, transparent, black),url('data:image/svg+xml;utf8, <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2"><path fill="white" d="M1,0H2V1H1V0ZM0,1H1V2H0V1Z"/><path fill="gray" d="M0,0H1V1H0V0ZM1,1H2V2H1V1Z"/></svg>');background-size:100%, 50%}

`;

然后再弄一个注册表,保证各个地方的颜色选择器获取到的颜色一致

import { 注册表 } from "siyuan-noob/commonStruct";

一开始的时候,我们就把主题目录下的 custom.css 重新插入回来(因为它被干掉了嘛)

let currentThemeElement =
  document.querySelector("#themeCustomStyle") ||
  document.querySelector("#themeStyle") ||
  document.querySelector("#themeDefaultStyle");
let currentThemeURL = currentThemeElement.getAttribute("href").split("?")[0];
if (!document.querySelector("#themeCustomStyle")) {
  let customThemeStyle = document.createElement("link");
  customThemeStyle.setAttribute("id", "themeCustomStyle");
  customThemeStyle.setAttribute("type", "text/css");
  customThemeStyle.setAttribute("rel", "stylesheet");
  customThemeStyle.setAttribute(
    "href",
    currentThemeURL.replace("theme.css", "custom.css")
  );
  document.head.appendChild(customThemeStyle);
}

然后还需要一个函数,用来从样式表元素(link 或者 style)来获取样式,就像这样

function getColor(element, name) {
  console.log(element.sheet)
  let rootRule
  for (let i = 0; i < element.sheet.cssRules.length; i++) {
    if (element.sheet.cssRules[i].selectorText === ":root") {
      rootRule = element.sheet.cssRules[i];
      break;
    }
  }
  let namedColor;
  namedColor = rootRule.style.getPropertyValue(name);
  namedColor = namedColor ? namedColor.trim() : null;
  return namedColor
}

再搞一个函数,用来临时设置样式

async function setstyle(items, save) {
  let tempstring = "";
  for (let item of items) {
    item.value !== undefined
      ? (tempstring = tempstring + item.id + ":" + item.value + ";\n")
      : null;
  }
  tempstring = "{" + tempstring + "}";
  let css = ":root" + tempstring;
  let styleSetterTemp = document.getElementById("styleSetterTemp");
  if (!styleSetterTemp) {
    styleSetterTemp = document.createElement("style");
    styleSetterTemp.innerText = css;
    styleSetterTemp.setAttribute("id", "styleSetterTemp");
    document.head.appendChild(styleSetterTemp);
  } else {
    styleSetterTemp.innerText = css;
    document.head.appendChild(styleSetterTemp);
  }
  save ? saveStyle(css) : null;
}

当确定下来之后,把它保存到 custom.css

async function saveStyle(css) {
  let blob = new Blob([css], {
    type: "text/css",
  });
  let file = new File([blob], "custom.css", {
    lastModified: Date.now(),
  });
  let data = new FormData();
  data.append(
    "path",
    "/conf/" + currentThemeURL.replace("theme.css", "custom.css")
  );
  data.append("file", file);
  data.append("isDir", false);
  data.append("modTime", Date.now());
  await fetch("/api/file/putFile", {
    method: "POST",
    body: data,
  });
  if (!document.querySelector("#themeCustomStyle")) {
    let customThemeStyle = document.createElement("link");
    customThemeStyle.setAttribute("id", "themeCustomStyle");
    customThemeStyle.setAttribute("type", "text/css");
    customThemeStyle.setAttribute("rel", "stylesheet");
    customThemeStyle.setAttribute(
      "href",
      currentThemeURL.replace("theme.css", "custom.css")
    );
    document.head.appendChild(customThemeStyle);
  } else {
    let customThemeStyle = document.querySelector("#themeCustomStyle");
    customThemeStyle.remove();
    document.head.appendChild(customThemeStyle);
  }
  document.querySelectorAll("#styleSetterTemp").forEach((el) => {
    el.remove();
  });
}

啊,终于可以开始写我们的 ThemeColorPicker 了

class ThemeColorPicker extends HTMLElement {
  constructor() {
    super();
    this.css变量注册表 = new 注册表("css变量");
  }
  getDefault() {
    try {
      let currentThemeElement =
        document.querySelector("#themeCustomStyle") ||
        document.querySelector("#themeStyle") ||
        document.querySelector("#themeDefaultStyle");
      this.defaultColor = getColor(currentThemeElement, this.name);
    } catch (e) {}
    if (!this.defaultColor) {
      this.defaultColor = getColor(
        document.querySelector("#themeStyle") ||
          document.querySelector("#themeDefaultStyle"),
        this.name
      );
    }
    if (!this.defaultColor) {
      this.defaultColor = getColor(
        document.querySelector("#themeDefaultStyle"),
        this.name
      );
    }
    return this.defaultColor;
  }
  connectedCallback() {
    document.getElementById("#pickrcss")
      ? null
      : document.head.insertAdjacentHTML(
          "beforeend",
          `      <style id='pickrcss'>
          ${pickClassic}

      </style>`
        );
    this.attachShadow({ mode: "open" });
    this.shadowRoot.innerHTML = `
    <style>
${pickClassic}
      </style>
      <link href="/stage/build/desktop/base.56dfeeea3d0c5f4a8fef.css" rel="stylesheet">
      <label class="b3-label fn__flex config__item">
    <div class="fn__flex-1 fn__flex-center">
    ${this.name}
    <div class="b3-label__text">${this.getAttribute("memo")}</div>
  
  </div>
    <span class="fn__space"></span>
    <span class="pickr"></span>

</label>
    `;
    if (this.getAttribute("simple")) {
      this.shadowRoot.innerHTML = `
      <style>
      ${pickClassic}
    
            </style>
            <link href="/stage/build/desktop/base.56dfeeea3d0c5f4a8fef.css" rel="stylesheet">
            <span class="pickr"></span>

    
      `;
    }
    this.pickr = Pickr.create({
      container: "body",
      el: this.shadowRoot.querySelector(".pickr"),
      default: this.getDefault(),
      theme: "classic", // or 'monolith', or 'nano'
      comparison: false,
      components: {
        preview: true,
        opacity: true,
        hue: true,
        interaction: {
          hex: true,
          rgba: true,
          hsla: true,
          hsva: true,
          cmyk: true,
          input: true,
          save: true,
          clear: true,
        },
      },
    });

    this.pickr.on("change", (color) => {
      let colorValue = color ? color.toRGBA() : "";
      this.css变量注册表.注册({
        id: this.name,
        value: colorValue,
      });
      setstyle(this.css变量注册表.list(), false);
    });
    this.pickr.on("save", (color) => {
      let colorValue = color ? color.toRGBA() : "";
      this.css变量注册表.注册({
        id: this.name,
        value: colorValue,
      });
      setstyle(this.css变量注册表.list(), true);
    });
    this.pickr.on("clear", (color) => {
      this.pickr.setColor(this.getDefault());
      this.css变量注册表.注销({
        id: this.name,
        value: undefined,
      });
      setstyle(this.css变量注册表.list(), true);
    });
  }

  static get observedAttributes() {
    return ["name"];
  }

  attributeChangedCallback(name, oldValue, newValue) {
    if (name === "name") {
      this.name = newValue;
    }
  }
}
customElements.define("theme-color-picker", ThemeColorPicker);

使用方法:

在主题中使用的时候,需要先运行这个代码片段,然后把运行产物(在 /snippets/jsInNote​里面)引入.

直接使用这个代码片段的话,在 html 块里面插入就行了

<theme-color-picker name="--b3-theme-background" memo="背景色" ></theme-color-picker>

theme-color-picker​元素的 name​属性就是要调节的 css 变量,memo​是显示出来的提示.

当然你也可以整点别的,simple 属性为 true​,这样可以自己写其他的部分,最后的效果反正就是这样:

image​​image

思源笔记折腾记录 - 运行你的笔记 - 链滴 (ld246.com)里面的方法来弄,运行到代码片段之后就可以用了

搞完收工,自己写主题配色器去吧~~

如果你想要了解更多原理的话,就自己去搜一下 stylesheet 对象吧,这个可以获取各种样式元素的规则,我就不罗嗦了.


水完收工,如果这玩意对你有用可以去爱发电给我买杯咖啡哒

leolee9086 正在创作一些简单的技术教程和小工具,以及设计方面内容 | 爱发电 (afdian.net)

  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    23606 引用 • 95752 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 程序员

    程序员是从事程序开发、程序维护的专业人员。

    578 引用 • 3533 回帖 • 1 关注
  • 分享

    有什么新发现就分享给大家吧!

    247 引用 • 1793 回帖
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 487 关注
  • Hexo

    Hexo 是一款快速、简洁且高效的博客框架,使用 Node.js 编写。

    21 引用 • 140 回帖 • 4 关注
  • Bootstrap

    Bootstrap 是 Twitter 推出的一个用于前端开发的开源工具包。它由 Twitter 的设计师 Mark Otto 和 Jacob Thornton 合作开发,是一个 CSS / HTML 框架。

    18 引用 • 33 回帖 • 665 关注
  • Swagger

    Swagger 是一款非常流行的 API 开发工具,它遵循 OpenAPI Specification(这是一种通用的、和编程语言无关的 API 描述规范)。Swagger 贯穿整个 API 生命周期,如 API 的设计、编写文档、测试和部署。

    26 引用 • 35 回帖 • 3 关注
  • Sublime

    Sublime Text 是一款可以用来写代码、写文章的文本编辑器。支持代码高亮、自动完成,还支持通过插件进行扩展。

    10 引用 • 5 回帖 • 3 关注
  • 游戏

    沉迷游戏伤身,强撸灰飞烟灭。

    178 引用 • 816 回帖
  • Oracle

    Oracle(甲骨文)公司,全称甲骨文股份有限公司(甲骨文软件系统有限公司),是全球最大的企业级软件公司,总部位于美国加利福尼亚州的红木滩。1989 年正式进入中国市场。2013 年,甲骨文已超越 IBM,成为继 Microsoft 后全球第二大软件公司。

    107 引用 • 127 回帖 • 365 关注
  • Flutter

    Flutter 是谷歌的移动 UI 框架,可以快速在 iOS 和 Android 上构建高质量的原生用户界面。 Flutter 可以与现有的代码一起工作,它正在被越来越多的开发者和组织使用,并且 Flutter 是完全免费、开源的。

    39 引用 • 92 回帖
  • Android

    Android 是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    334 引用 • 323 回帖 • 1 关注
  • danl
    153 关注
  • 微信

    腾讯公司 2011 年 1 月 21 日推出的一款手机通讯软件。用户可以通过摇一摇、搜索号码、扫描二维码等添加好友和关注公众平台,同时可以将自己看到的精彩内容分享到微信朋友圈。

    132 引用 • 796 回帖 • 1 关注
  • Facebook

    Facebook 是一个联系朋友的社交工具。大家可以通过它和朋友、同事、同学以及周围的人保持互动交流,分享无限上传的图片,发布链接和视频,更可以增进对朋友的了解。

    4 引用 • 15 回帖 • 438 关注
  • TextBundle

    TextBundle 文件格式旨在应用程序之间交换 Markdown 或 Fountain 之类的纯文本文件时,提供更无缝的用户体验。

    1 引用 • 2 回帖 • 56 关注
  • Laravel

    Laravel 是一套简洁、优雅的 PHP Web 开发框架。它采用 MVC 设计,是一款崇尚开发效率的全栈框架。

    20 引用 • 23 回帖 • 728 关注
  • 阿里云

    阿里云是阿里巴巴集团旗下公司,是全球领先的云计算及人工智能科技公司。提供云服务器、云数据库、云安全等云计算服务,以及大数据、人工智能服务、精准定制基于场景的行业解决方案。

    89 引用 • 345 回帖
  • PWA

    PWA(Progressive Web App)是 Google 在 2015 年提出、2016 年 6 月开始推广的项目。它结合了一系列现代 Web 技术,在网页应用中实现和原生应用相近的用户体验。

    14 引用 • 69 回帖 • 162 关注
  • 代码片段

    代码片段分为 CSS 与 JS 两种代码,添加在 [设置 - 外观 - 代码片段] 中,这些代码会在思源笔记加载时自动执行,用于改善笔记的样式或功能。

    用户在该标签下分享代码片段时需在帖子标题前添加 [css] [js] 用于区分代码片段类型。

    104 引用 • 722 回帖
  • Maven

    Maven 是基于项目对象模型(POM)、通过一小段描述信息来管理项目的构建、报告和文档的软件项目管理工具。

    186 引用 • 318 回帖 • 275 关注
  • GAE

    Google App Engine(GAE)是 Google 管理的数据中心中用于 WEB 应用程序的开发和托管的平台。2008 年 4 月 发布第一个测试版本。目前支持 Python、Java 和 Go 开发部署。全球已有数十万的开发者在其上开发了众多的应用。

    14 引用 • 42 回帖 • 779 关注
  • Scala

    Scala 是一门多范式的编程语言,集成面向对象编程和函数式编程的各种特性。

    13 引用 • 11 回帖 • 149 关注
  • Mac

    Mac 是苹果公司自 1984 年起以“Macintosh”开始开发的个人消费型计算机,如:iMac、Mac mini、Macbook Air、Macbook Pro、Macbook、Mac Pro 等计算机。

    166 引用 • 595 回帖 • 1 关注
  • PHP

    PHP(Hypertext Preprocessor)是一种开源脚本语言。语法吸收了 C 语言、 Java 和 Perl 的特点,主要适用于 Web 开发领域,据说是世界上最好的编程语言。

    179 引用 • 407 回帖 • 487 关注
  • PWL

    组织简介

    用爱发电 (Programming With Love) 是一个以开源精神为核心的民间开源爱好者技术组织,“用爱发电”象征开源与贡献精神,加入组织,代表你将遵守组织的“个人开源爱好者”的各项条款。申请加入:用爱发电组织邀请帖
    用爱发电组织官网:https://programmingwithlove.stackoverflow.wiki/

    用爱发电组织的核心驱动力:

    • 遵守开源守则,体现开源&贡献精神:以分享为目的,拒绝非法牟利。
    • 自我保护:使用适当的 License 保护自己的原创作品。
    • 尊重他人:不以各种理由、各种漏洞进行未经允许的抄袭、散播、洩露;以礼相待,尊重所有对社区做出贡献的开发者;通过他人的分享习得知识,要留下足迹,表示感谢。
    • 热爱编程、热爱学习:加入组织,热爱编程是首当其要的。我们欢迎热爱讨论、分享、提问的朋友,也同样欢迎默默成就的朋友。
    • 倾听:正确并恳切对待、处理问题与建议,及时修复开源项目的 Bug ,及时与反馈者沟通。不抬杠、不无视、不辱骂。
    • 平视:不诋毁、轻视、嘲讽其他开发者,主动提出建议、施以帮助,以和谐为本。只要他人肯努力,你也可能会被昔日小看的人所超越,所以请保持谦虚。
    • 乐观且活跃:你的努力决定了你的高度。不要放弃,多年后回头俯瞰,才会发现自己已经成就往日所仰望的水平。积极地将项目开源,帮助他人学习、改进,自己也会获得相应的提升、成就与成就感。
    1 引用 • 487 回帖 • 1 关注
  • IBM

    IBM(国际商业机器公司)或万国商业机器公司,简称 IBM(International Business Machines Corporation),总公司在纽约州阿蒙克市。1911 年托马斯·沃森创立于美国,是全球最大的信息技术和业务解决方案公司,拥有全球雇员 30 多万人,业务遍及 160 多个国家和地区。

    17 引用 • 53 回帖 • 143 关注
  • JavaScript

    JavaScript 一种动态类型、弱类型、基于原型的直译式脚本语言,内置支持类型。它的解释器被称为 JavaScript 引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在 HTML 网页上使用,用来给 HTML 网页增加动态功能。

    729 引用 • 1275 回帖 • 2 关注