Giter Site home page Giter Site logo

Comments (25)

mosen avatar mosen commented on August 23, 2024

Let me compare against an OpenSuSE 12.3 VM, I suspect that the cups package has several differences, maybe due to my platform (osx) shipping with a slightly older version?

from puppet-cups.

mosen avatar mosen commented on August 23, 2024

At the moment it looks like some options are only set when the queue is created. So I have to write a list of parameters for options that are "create only" options.

from puppet-cups.

itsbo avatar itsbo commented on August 23, 2024

Please make them single options instead of an array, like "options" or "ppd_options". The inconvenience with "options" and "ppd_options" is that you can set them as defaults only as a whole, not individual things like "Media Size" etc..

from puppet-cups.

mosen avatar mosen commented on August 23, 2024

It's easy enough to set the standard ones as individual properties. I can't really do that with vendor options (eg. stapler, composite overprint), because every PPD provides different options.
I can add PageSize, InputSlot, Collate, MediaType etc.. if that helps?

from puppet-cups.

itsbo avatar itsbo commented on August 23, 2024

The most interesting options would probably be "PageSize", "Duplex" and "ColorModel", as many people I know prefer for users to print duplex and B/W by default in order to conserve Paper/Toner across all devices and set the default PaperSize that is standard for their country. I personally can't say to have used the other options.

"PageSize", "Duplex" and "ColorModel" have defined parameters according to the PPD specs (http://partners.adobe.com/public/developer/en/ps/5003.PPD_Spec_v4.3.pdf), so no vendor problems.

You might want to check for printers that are not Colour and have no Duplex unit and therefore do not have those PPD Options. I'd guess people will be tempted to just set the options globally across all devices if you choose to implement them.

Thank you for your time and effort.

from puppet-cups.

itsbo avatar itsbo commented on August 23, 2024

With your current patch and "job-sheets" set in my config it constantly refreshes again.

from puppet-cups.

mosen avatar mosen commented on August 23, 2024

Sorry about that. My intention was to provide ppd_options for options listed in lpoptions -p <dest> -l, and others via options. The options "PageSize", "Duplex" etc are settable via lpoptions for me, am i correct in reading that you are setting those from lpadmin? I'm having a difficult time separating the options that would be accepted by lpoptions and lpadmin because the results seem to be inconsistent. In the mean time, I will check the PPD spec and add "PageSize" "Duplex" and "ColorModel".

The whole options v ppd_options thing might need a backwards incompatible rewrite.

from puppet-cups.

itsbo avatar itsbo commented on August 23, 2024

The patch I described in my first post worked for me. I would suggest setting everything that gets listed via lpoptions -p <dest> with lpoptions (putting it in "options") and everything that gets listed via lpoptions -p <dest> -l (putting it in ppd_options) via lpadmin. So far those two sets did not overlap on my Linux-box and it worked this far.

from puppet-cups.

jyaworski avatar jyaworski commented on August 23, 2024

I may be having a related issue. It seems like whenever I apply a printer that has ppd_options listed, it always reports that there are changes to those printers coming from Puppet. I have not tested with options, only ppd_options.

I'm on bb9c152

from puppet-cups.

mosen avatar mosen commented on August 23, 2024

It's looking more like osx has a different fork of cups, or something similar. Because the options behavior i get is actually the opposite of what @itsbo is describing. I'll run up an OpenSuSE VM to make sure I'm not going crazy.

from puppet-cups.

mosen avatar mosen commented on August 23, 2024

I started a vagrant box with OpenSuSE 12.3 and cups.
Added a test printer/queue which just used the generic postscript model.

  • PageSize is an option given by lpoptions -p <dest> -l
  • I try to set PageSize using the command lpoptions -p <dest> -o PageSize=A4, the default was Letter.
  • Success, PageSize now equals A4. (verified by output of lpoptions -p <dest> and lpoptions -p <dest> -l).
  • I try to set PageSize using the command lpadmin -p <dest> -o PageSize=B5.
  • lpoptions -p <dest> and lpoptions -p <dest> -l both show that PageSize is unchanged from earlier (the value is still A4).

I cannot seem to replicate what you are saying about lpadmin controlling the printer-specific options from lpoptions -p <dest> -l.

This is what my understanding is so far:

  • Any option listed in the lpadmin manpage can only be used with lpadmin. This includes stuff like printer-is-shared and printer-error-policy.
  • Some of the short switch options can be set with lpadmin, like setting device-uri instead of using a -v switch to lpadmin. eg. lpadmin -p <dest> -o device-uri=ipp://127.0.0.1/test.
  • Vendor extensions, or PPD specific options (lpoptions -p <dest> -l), I can only set using lpoptions -p <dest> -o Name=value.
  • There are other options that don't appear anywhere except lpoptions -p that are changeable only by lpoptions -p <dest> -o name=value, one example is copies=2.

Tell me if this is inconsistent with what you are seeing?

from puppet-cups.

itsbo avatar itsbo commented on August 23, 2024

I just checked and I think I see what is happening here:

  • If I change the papersize with lpoptions -p <dest> -o PageSize=A4 from letter, it will be reflected by the output of lpoptions -p <dest> and lpoptions -p <dest> -l, like you said.
  • If I change the papersize with ladmin -p <dest> -o PageSize=A4, from letter it will be reflected by the webpage
    • Strangeness: The output of lpoptions -p <dest> and lpoptions -p <dest> -l still tells me I have Letter

So which one is it?

from puppet-cups.

mosen avatar mosen commented on August 23, 2024

also try (if you can) sudo lpoptions -p <dest> -o PageSize=A4. If you run lpoptions as a user, it will modify just ~/.cups/lpoptions, but as root it changes the options for everyone in /etc/cups/lpoptions.

I think that might be why the webpage on localhost:631 will show Letter even though you ran lpoptions -p <dest> -o PageSize=A4.

I don't know why lpadmin -p <dest> -o PageSize=A4 works for you, but not for me. I still need to test a few different systems.

from puppet-cups.

itsbo avatar itsbo commented on August 23, 2024

I did run the commands as root. You are right, lpoptions -p <dest> -o PageSize=A4 modified /etc/cups/lpoptions so that explains the output of the commandline tools. If I delete the file the output reverts back to what the webpage says.

from puppet-cups.

mosen avatar mosen commented on August 23, 2024

Hi itsbo, just got back from vacation.
I added virtual machine tests to the repo in order to test other platforms and confirm that each option was working as intended. With the current head branch are you still getting issues setting options?

from puppet-cups.

dionysius avatar dionysius commented on August 23, 2024

Hi @mosen @itsbo

I've spend several hours to understand how cups is handling that settings and yes, its very confusing! I'm running on Ubuntu 14.04 using standard default repo cups, puppet and puppet-cups.

The problem here is, there are 3 different active configs for a printer. I name them: global config, global options, user options. TESTING is my printer name.
The global config is stored /etc/cups/ppd/TESTING.ppd
The global options is stored /etc/cups/lpoptions
The user options is stored ~/.cups/lpoptions

Another problem is to understand, where gui's (e.g. system-config-printer) or cups-webgui save its settings - but I going in here by using only CLI commands. The only way to get option-settings (without parsing the ppd file) is using 'lpoptions -p PRINTER -l' as far as I found. I assume that puppet-cups wants to update global settings (or at least what I'm in for).

It seems like there is a recoursive path obtaining the informations for lpoptoins. As user it goes through 'user option' > 'global options' > 'global config'. As root it goes only through 'global options' > 'global config'. So far so understandable.

A fresh installation of a printer looks like this: (I will concatenate this commands in the future)

$ grep "DefaultPageSize" /etc/cups/ppd/TESTING.ppd
*DefaultPageSize: A4
$ sudo cat /etc/cups/lpoptions 
Default TESTING
$ cat ~/.cups/lpoptions
cat: /home/localadmin/.cups/lpoptions: File not found

So our first lpoptions output looks like this (first root, second user):

$ sudo su - root -c "lpoptions -p TESTING -l | grep PageSize" ; lpoptions -p TESTING -l | grep PageSize
PageSize/Media Size: A3 *A4 A5 A6 B4 B5 ISOB5 B6 OficioII Folio Statement P8K P16K OficioMX P12X18 Letter Legal Executive Tabloid EnvPersonal Env9 Env10 EnvMonarch EnvDL EnvC5 EnvC4 Custom.WIDTHxHEIGHT
PageSize/Media Size: A3 *A4 A5 A6 B4 B5 ISOB5 B6 OficioII Folio Statement P8K P16K OficioMX P12X18 Letter Legal Executive Tabloid EnvPersonal Env9 Env10 EnvMonarch EnvDL EnvC5 EnvC4 Custom.WIDTHxHEIGHT

So far so good. Lets play around, lets give another Letter format using lpadmin:

$ sudo lpadmin -p TESTING -o PageSize=A3
$ sudo grep "DefaultPageSize" /etc/cups/ppd/TESTING.ppd ; sudo cat /etc/cups/lpoptions ; cat ~/.cups/lpoptions ;
*DefaultPageSize: A3
Default TESTING
cat: /home/localadmin/.cups/lpoptions: Datei oder Verzeichnis nicht gefunden
$ sudo su - root -c "lpoptions -p TESTING -l | grep PageSize" ; lpoptions -p TESTING -l | grep PageSize
PageSize/Media Size: *A3 A4 A5 A6 B4 B5 ISOB5 B6 OficioII Folio Statement P8K P16K OficioMX P12X18 Letter Legal Executive Tabloid EnvPersonal Env9 Env10 EnvMonarch EnvDL EnvC5 EnvC4 Custom.WIDTHxHEIGHT
PageSize/Media Size: *A3 A4 A5 A6 B4 B5 ISOB5 B6 OficioII Folio Statement P8K P16K OficioMX P12X18 Letter Legal Executive Tabloid EnvPersonal Env9 Env10 EnvMonarch EnvDL EnvC5 EnvC4 Custom.WIDTHxHEIGHT

So lets change the next level using sudo lpoptions

$ sudo lpoptions -p TESTING -o PageSize=A5
~$ sudo grep "DefaultPageSize" /etc/cups/ppd/TESTING.ppd ; sudo cat /etc/cups/lpoptions ; cat ~/.cups/lpoptions ;
*DefaultPageSize: A3
Default TESTING PageSize=A5
cat: /home/localadmin/.cups/lpoptions: Datei oder Verzeichnis nicht gefunden
$ sudo su - root -c "lpoptions -p TESTING -l | grep PageSize" ; lpoptions -p TESTING -l | grep PageSize
PageSize/Media Size: A3 A4 *A5 A6 B4 B5 ISOB5 B6 OficioII Folio Statement P8K P16K OficioMX P12X18 Letter Legal Executive Tabloid EnvPersonal Env9 Env10 EnvMonarch EnvDL EnvC5 EnvC4 Custom.WIDTHxHEIGHT
PageSize/Media Size: A3 A4 *A5 A6 B4 B5 ISOB5 B6 OficioII Folio Statement P8K P16K OficioMX P12X18 Letter Legal Executive Tabloid EnvPersonal Env9 Env10 EnvMonarch EnvDL EnvC5 EnvC4 Custom.WIDTHxHEIGHT

Let's move on and finally setup another pagesetup for the user

$ lpoptions -p TESTING -o PageSize=A6
$ sudo grep "DefaultPageSize" /etc/cups/ppd/TESTING.ppd ; sudo cat /etc/cups/lpoptions ; cat ~/.cups/lpoptions ;
*DefaultPageSize: A3
Default TESTING PageSize=A5
Default TESTING PageSize=A6
$ sudo su - root -c "lpoptions -p TESTING -l | grep PageSize" ; lpoptions -p TESTING -l | grep PageSize
PageSize/Media Size: A3 A4 *A5 A6 B4 B5 ISOB5 B6 OficioII Folio Statement P8K P16K OficioMX P12X18 Letter Legal Executive Tabloid EnvPersonal Env9 Env10 EnvMonarch EnvDL EnvC5 EnvC4 Custom.WIDTHxHEIGHT
PageSize/Media Size: A3 A4 A5 *A6 B4 B5 ISOB5 B6 OficioII Folio Statement P8K P16K OficioMX P12X18 Letter Legal Executive Tabloid EnvPersonal Env9 Env10 EnvMonarch EnvDL EnvC5 EnvC4 Custom.WIDTHxHEIGHT

So far somehow also understandable. But now following questions: why are there 2 different global configs when they share the same functionality for the enduser? (currently not answerable i think) And more importantly, what happens if a user uses http://localhost:631 and change the PageSize to something other? Lets try it out (I only changed to format B4 - and it was A3):

$ sudo grep "DefaultPageSize" /etc/cups/ppd/TESTING.ppd ; sudo cat /etc/cups/lpoptions ; cat ~/.cups/lpoptions ;
*DefaultPageSize: B4
Default TESTING PageSize=A5
Default TESTING PageSize=A6
$ sudo su - root -c "lpoptions -p TESTING -l | grep PageSize" ; lpoptions -p TESTING -l | grep PageSize
PageSize/Media Size: A3 A4 *A5 A6 B4 B5 ISOB5 B6 OficioII Folio Statement P8K P16K OficioMX P12X18 Letter Legal Executive Tabloid EnvPersonal Env9 Env10 EnvMonarch EnvDL EnvC5 EnvC4 Custom.WIDTHxHEIGHT
PageSize/Media Size: A3 A4 A5 *A6 B4 B5 ISOB5 B6 OficioII Folio Statement P8K P16K OficioMX P12X18 Letter Legal Executive Tabloid EnvPersonal Env9 Env10 EnvMonarch EnvDL EnvC5 EnvC4 Custom.WIDTHxHEIGHT

Now you gonna think, what the hell, where is my B4? puppet-cups cannot read the current settings of the printer with lpoptions only. cups-webgui (and also system-config-printer) do not care about global options, but puppet-cups will care, because once the global options are set, its impossible to find out the global config without parsing the ppd directly and so its impossible to sync the configured reciepe in the puppet master.

I think we have 2 options here: Either we're going to implement a method to parse the ppd and manage it that way like cups itself does and never touch global options (more difficult) - or we're going to ignore the global options by resetting them always before reading the current global config (easier - but hacky workaround)

Let me show you now how to clean up each level. User level first:

$ rm -rf ~/.cups
$ sudo grep "DefaultPageSize" /etc/cups/ppd/TESTING.ppd ; sudo cat /etc/cups/lpoptions ; cat ~/.cups/lpoptions ;
*DefaultPageSize: B4
Default TESTING PageSize=A5
cat: /home/localadmin/.cups/lpoptions: Datei oder Verzeichnis nicht gefunden
$ sudo su - root -c "lpoptions -p TESTING -l | grep PageSize" ; lpoptions -p TESTING -l | grep PageSize
PageSize/Media Size: A3 A4 *A5 A6 B4 B5 ISOB5 B6 OficioII Folio Statement P8K P16K OficioMX P12X18 Letter Legal Executive Tabloid EnvPersonal Env9 Env10 EnvMonarch EnvDL EnvC5 EnvC4 Custom.WIDTHxHEIGHT
PageSize/Media Size: A3 A4 *A5 A6 B4 B5 ISOB5 B6 OficioII Folio Statement P8K P16K OficioMX P12X18 Letter Legal Executive Tabloid EnvPersonal Env9 Env10 EnvMonarch EnvDL EnvC5 EnvC4 Custom.WIDTHxHEIGHT

And now reset the global options:

$ sudo lpoptions -x TESTING
$ sudo grep "DefaultPageSize" /etc/cups/ppd/TESTING.ppd ; sudo cat /etc/cups/lpoptions ; cat ~/.cups/lpoptions ;
*DefaultPageSize: B4
Default TESTING
cat: /home/localadmin/.cups/lpoptions: Datei oder Verzeichnis nicht gefunden
$ sudo su - root -c "lpoptions -p TESTING -l | grep PageSize" ; lpoptions -p TESTING -l | grep PageSize
PageSize/Media Size: A3 A4 A5 A6 *B4 B5 ISOB5 B6 OficioII Folio Statement P8K P16K OficioMX P12X18 Letter Legal Executive Tabloid EnvPersonal Env9 Env10 EnvMonarch EnvDL EnvC5 EnvC4 Custom.WIDTHxHEIGHT
PageSize/Media Size: A3 A4 A5 A6 *B4 B5 ISOB5 B6 OficioII Folio Statement P8K P16K OficioMX P12X18 Letter Legal Executive Tabloid EnvPersonal Env9 Env10 EnvMonarch EnvDL EnvC5 EnvC4 Custom.WIDTHxHEIGHT

Now we see the information we're interested in to be able to sync the settings. But keep in mind, that it is actually not a bug by puppet-cups, since the user gets always the correct information. It is just annoying, when using the different managers that it looks like it is not synced (and any changes to them are just ignored, because it will be overriden)

Tell me what you think, I hope my post is understandable somehow :)

from puppet-cups.

dionysius avatar dionysius commented on August 23, 2024

Now the most confusing part (i thought I covered everything):
Even rebooting my laptop after puppet setup and the config files local look fine. Why is now my PageSize in the Print-Dialog (e.g. firefox) on 'US-Letter'? It's like now I don't know nothing... :(

from puppet-cups.

mosen avatar mosen commented on August 23, 2024

Thanks for all the research. It is a very inconsistent behavior! What I will do next is check the webgui config on localhost:631 to see what's being modified. On Mac OS X, cups does not control the print dialog defaults, so maybe you are seeing the same problem on Ubuntu. The user options ~/.cups/lpoptions are only used on OSX when you submit a job via lpr, so I think there is good reason to suspect that the webgui options are being applied when jobs are submitted in some other way. In any case, I will have to do some more reading and experiment with calling the web API directly if that's what we need to do to have all of the options sync up.

from puppet-cups.

mosen avatar mosen commented on August 23, 2024

After some additional research I think I've found a bit more clarity on the issue.

  • lpoptions is almost irrelevant, actually. Options set in ~/.cups/lpoptions and /etc/cups/lpoptions are not always used, so the behavior seems really inconsistent when you print remotely/from different applications etc.
  • I did not understand Itsbo when he said he was using lpadmin -p <printer> -o PageSize=XX, but you CAN do this, but only when creating a printer. You can't modify an existing printer to change the options. The reason is that options supplied to lpadmin are applied directly to the ppd in /etc/cups/ppd/<printer>.ppd, where as lpoptions only applies them to the lpoptions file.
  • The only reliable way to change printer options after the printer has been added, is through the web interface. This is because it is the only method which directly edits the PPD file.

The outcome of this is that the design of puppet-cups has to change in one of two ways:

  • Quick and dirty version: Options are only available as create-time parameters.
  • More flexible version: Support PPD editing directly, or find a CUPS API which modifies only the relevant option in the PPD.

from puppet-cups.

mosen avatar mosen commented on August 23, 2024

OK. I rewrote options handling like this in feature branch feature/ppd_options_params.
PPD options have all been converted to parameters, and are supplied to lpadmin on creation.
I wrote a simple beaker test to verify that this works by setting page_size, et voila, everything works as intended.

I will refine this feature branch then merge and tag it as the v2.0 release candidate, seeing as the options handling breaks backwards compatibility in a BIG way.

from puppet-cups.

itsbo avatar itsbo commented on August 23, 2024

This might be version dependent or a bug.

I rechecked with a Ubuntu 12.04 LTS (cups 1.5.2) and lpadmin -p <printer> -o PageSize=XXwon't change a created printer.

Ubuntu:~# lpadmin -p printer -o PageSize=Letter
Ubuntu:~# lpoptions -p printer -l|grep Letter
PageSize/Media Size: A3 *A4 A5 A6 B4 B5 B6 Legal GovernmentLG EngQuatro Letter Statement F Folio FanFoldGermanLegal Tabloid 12x18 11x15 10x14 Executive Env10 EnvMonarch EnvC5 EnvC6 DLEnv 8Kai 16Kai A3.FullBleed A4.FullBleed A5.FullBleed A6.FullBleed B4.FullBleed B5.FullBleed B6.FullBleed Legal.FullBleed GovernmentLG.FullBleed EngQuatro.FullBleed Letter.FullBleed Statement.FullBleed F.FullBleed Folio.FullBleed FanFoldGermanLegal.FullBleed Tabloid.FullBleed 12x18.FullBleed 11x15.FullBleed 10x14.FullBleed Executive.FullBleed Env10.FullBleed EnvMonarch.FullBleed EnvC5.FullBleed EnvC6.FullBleed DLEnv.FullBleed 8Kai.FullBleed 16Kai.FullBleed Custom.WIDTHxHEIGHT

I issued the same on an OpenSuSE 12.3 (Cups 1.5.4) and it does change the printer:

OpenSuSE:~ # lpoptions -p printer -l|grep B4
PageSize/Media Size: Letter LetterSmall Legal LegalSmall Executive Tabloid A3 A4 A4Small A5 ISOB5 B5 *B4 w612h936 DoublePostcard w774h1116 w558h774 EnvISOB5 Env10 EnvC5 EnvDL EnvMonarch Custom.WIDTHxHEIGHT
OpenSuSE:~ # lpadmin -p printer -o PageSize=A4
OpenSuSE:~ # lpoptions -p printer -l|grep A4
PageSize/Media Size: Letter LetterSmall Legal LegalSmall Executive Tabloid A3 *A4 A4Small A5 ISOB5 B5 B4 w612h936 DoublePostcard w774h1116 w558h774 EnvISOB5 Env10 EnvC5 EnvDL EnvMonarch Custom.WIDTHxHEIGHT

Didn't wade through the changelogs to confirm this though.

from puppet-cups.

ckaenzig avatar ckaenzig commented on August 23, 2024

Hi,

I've been playing with this module and pulling my hair trying to understand how cups manages it's options (like everyone else it seems).

I'm using Ubuntu 14.04 and seeing another weird behavior that doesn't seems listed here yet. I'm trying to set default vendor options Finisher and OptionTray. Setting these options using the ppd_options parameter currently (using master branch) in /etc/cups/lpoptions, but not in the .ppd. This works well with software using Ubuntu's printing system (some kind of library / layer on top of cups), or software that seems to handle lpotions itself (e.g. LibreOffice). It does not work with other software (in my case Acrobat Reader) that builds its lpr command itself and seems to parse the .ppd file for default options.

What I've found is that when the lpadmin command is run to install the printer, the supplied options are completely ignored. But if I run the exact same command again, the existing .ppd file is changed with the defaults I want. This seems to be completely opposite to what @mosen found on his system.

Here is the command I'm using:

/usr/sbin/lpadmin -p "TESTPRINTER" -E -v"socket://10.27.10.213" -m"openprinting-ppds:0/ppd/openprinting/Infotec/PS/Infotec-MP_C3003_PS.ppd" -o printer-is-shared=false -o Finisher=FinAMURBK -o OptionTray=2Cassette

Once the options are set in the .ppd file (and without a /etc/cups/lpoptions file present), all my programs are happy and use the correct default options (including lpoptions -P TESTPRINTER -l and the cups web gui).

A fix that works for me is to replace the lpoptions command at https://github.com/mosen/puppet-cups/blob/master/lib/puppet/provider/printer/cups.rb#L354 with the lpadmin command (same arguments). Though, I haven't yet played with paper size options and such, so I'm hoping it will work the same way...).

Edit: I just noticed that this fix is actually the same that @itsbo suggested in the first message.

I don't think it is useful I submit a pull request as it probably only works for me. I'm hoping this information can be helpful for debugging or for other people having the same issue. Please let me know if I can help.

from puppet-cups.

mosen avatar mosen commented on August 23, 2024

I'll review using lpadmin again for every case of options. I'm using it on creation at the moment, since it seemed like cups only generated the altered PPD when creating a queue. There are some options that can be changed after creation and some that cannot.

It's not extremely clear how to separate options that are available at creation time. But it looks like a few of you are having issues unless you use lpadmin, so I will have to run with that.

@ckaenzig You can submit a pull, or i can just merge it into HEAD.

from puppet-cups.

mosen avatar mosen commented on August 23, 2024

I've merged this option handling. Hopefully it works for everybody else. I can't confirm this on my own machine so I will write an acceptance test for Ubuntu 14.

from puppet-cups.

mosen avatar mosen commented on August 23, 2024

Acceptance test is passing for options and ppd_options at the moment. Because this issue turned into a discussion forum I'm closing it. If there are still issues with options or ppd_options in github please start another issue.

from puppet-cups.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.